GithubHelp home page GithubHelp logo

miketheman / pytest-socket Goto Github PK

View Code? Open in Web Editor NEW
265.0 6.0 41.0 445 KB

Pytest Plugin to disable socket calls during tests

Home Page: https://pypi.org/project/pytest-socket/

License: MIT License

Python 97.41% Makefile 2.59%
pytest-plugin socket python testing testing-tools

pytest-socket's Introduction

pytest-socket

PyPI current version Python Support Tests pre-commit.ci status Maintainability FOSSA Status Code style: black

A plugin to use with Pytest to disable or restrict socket calls during tests to ensure network calls are prevented.


Features

  • Disables all network calls flowing through Python's socket interface.

Requirements

Installation

You can install pytest-socket via pip from PyPI:

pip install pytest-socket

or add to your pyproject.toml for poetry:

[tool.poetry.dev-dependencies]
pytest-socket = "*"

Usage

Run pytest --disable-socket, tests should fail on any access to socket or libraries using socket with a SocketBlockedError.

To add this flag as the default behavior, add this section to your pytest.ini:

[pytest]
addopts = --disable-socket

or add this to your setup.cfg:

[tool:pytest]
addopts = --disable-socket

or update your conftest.py to include:

from pytest_socket import disable_socket

def pytest_runtest_setup():
    disable_socket()

If you exceptionally want to enable socket for one particular execution pass --force-enable-socket. It takes precedence over --disable-socket.

To enable Unix sockets during the test run (e.g. for async), add this option:

[pytest]
addopts = --disable-socket --allow-unix-socket

To enable specific tests use of socket, pass in the fixture to the test or use a marker:

def test_explicitly_enable_socket(socket_enabled):
    assert socket.socket(socket.AF_INET, socket.SOCK_STREAM)


@pytest.mark.enable_socket
def test_explicitly_enable_socket_with_mark():
    assert socket.socket(socket.AF_INET, socket.SOCK_STREAM)

To allow only specific hosts per-test:

@pytest.mark.allow_hosts(['127.0.0.1'])
def test_explicitly_enable_socket_with_mark():
    assert socket.socket.connect(('127.0.0.1', 80))

or for whole test run

[pytest]
addopts = --allow-hosts=127.0.0.1,127.0.1.1

Frequently Asked Questions

Q: Why is network access disabled in some of my tests but not others?

A: pytest's default fixture scope is "function", which socket_enabled uses. If you create another fixture that creates a socket usage that has a "higher" instantiation order, such as at the module/class/session, then the higher order fixture will be resolved first, and won't be disabled during the tests. Read more in this excellent example and more about pytest fixture order here.

This behavior may change in the future, as we learn more about pytest fixture order, and what users expect to happen.

Contributing

Contributions are very welcome. Tests can be run with pytest, please ensure the coverage at least stays the same before you submit a pull request.

License

Distributed under the terms of the MIT license, "pytest-socket" is free and open source software

FOSSA Status

Issues

If you encounter any problems, please file an issue along with a detailed description.

References

This Pytest plugin was generated with Cookiecutter along with @hackebrot's Cookiecutter-pytest-plugin template.

This plugin came about due to the efforts by @hangtwenty solving a StackOverflow question, then converted into a pytest plugin by @miketheman.

pytest-socket's People

Contributors

andreoliwa avatar atugushev avatar cabarnes avatar dependabot[bot] avatar emontnemery avatar fabaff avatar fossabot avatar hasier avatar joetsoi avatar kianmeng avatar klette avatar kwshi avatar llimllib avatar magnasilvar avatar matthewwardrop avatar mgaitan avatar miketheman avatar ollipa avatar pre-commit-ci[bot] avatar renovate-bot avatar renovate[bot] avatar sadams avatar scop avatar sourcery-ai-bot avatar valgur avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

pytest-socket's Issues

Incompatibility with pytest-flakes?

After updating pytest-socket to the 0.5.0 version, I cannot use pytest-socket (0.5.0) and pytest-flakes (4.0.5) together.
I see the following error:

item = <FlakesItem flake-8>

    def pytest_runtest_setup(item) -> None:
        """During each test item's setup phase,
        choose the behavior based on the configurations supplied.
    
        This is the bulk of the logic for the plugin.
        As the logic can be extensive, this method is allowed complexity.
        It may be refactored in the future to be more readable.
        """
    
        # If test has the `enable_socket` marker, we accept this as most explicit.
>       if "socket_enabled" in item.fixturenames or item.get_closest_marker(
            "enable_socket"
        ):
E       AttributeError: 'FlakesItem' object has no attribute 'fixturenames'

The 0.4.1 version working well.

Is there a "disable_socket" mark?

Hi,

Thanks for your hard work and useful plugin.

What if there's a minority X tests out of Y tests that I want to disable connections for? Is there a @pytest.mark.disable_socket so we can selectively disable sockets on specific tests? I couldn't find anything for that in the docs. It would be much more useful in my case than adding @pytest.mark.enable_socket to my Y-X tests (which are the majority of my tests).

Host Whitelisting

It seems that asynctest requires at least localhost sockets when I ran my test. Would it be possible to selectively enable certain sockets and not others? For example, here I would probably get past this if I could allow localhost sockets.

============================================== FAILURES ===============================================
______________________ TestBot.test__sends_error_message_when_connection_refused ______________________
venv/lib/python3.6/site-packages/asynctest/case.py:272: in run
    self._setUp()
venv/lib/python3.6/site-packages/asynctest/case.py:217: in _setUp
    self._init_loop()
venv/lib/python3.6/site-packages/asynctest/case.py:172: in _init_loop
    loop = self.loop = asyncio.new_event_loop()
/usr/lib64/python3.6/asyncio/events.py:688: in new_event_loop
    return get_event_loop_policy().new_event_loop()
/usr/lib64/python3.6/asyncio/events.py:599: in new_event_loop
    return self._loop_factory()
/usr/lib64/python3.6/asyncio/unix_events.py:56: in __init__
    super().__init__(selector)
/usr/lib64/python3.6/asyncio/selector_events.py:67: in __init__
    self._make_self_pipe()
/usr/lib64/python3.6/asyncio/selector_events.py:129: in _make_self_pipe
    self._ssock, self._csock = self._socketpair()
/usr/lib64/python3.6/asyncio/unix_events.py:60: in _socketpair
    return socket.socketpair()
/usr/lib64/python3.6/socket.py:489: in socketpair
    a = socket(family, type, proto, a.detach())
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

args = (<AddressFamily.AF_UNIX: 1>, <SocketKind.SOCK_STREAM: 1>, 0, 11), kwargs = {}

    def guarded(*args, **kwargs):
>       raise SocketBlockedError()
E       pytest_socket.SocketBlockedError: A test tried to use socket.socket.

venv/lib/python3.6/site-packages/pytest_socket.py:56: SocketBlockedError
================================= 1 failed, 4 passed in 0.41 seconds ==================================
Exception ignored in: <bound method BaseEventLoop.__del__ of <_UnixSelectorEventLoop running=False closed=False debug=False>>
Traceback (most recent call last):
  File "/usr/lib64/python3.6/asyncio/base_events.py", line 512, in __del__
    self.close()
  File "/usr/lib64/python3.6/asyncio/unix_events.py", line 63, in close
    super().close()
  File "/usr/lib64/python3.6/asyncio/selector_events.py", line 110, in close
    self._close_self_pipe()
  File "/usr/lib64/python3.6/asyncio/selector_events.py", line 120, in _close_self_pipe
    self._remove_reader(self._ssock.fileno())
AttributeError: '_UnixSelectorEventLoop' object has no attribute '_ssock'

To reproduce:
pytest.ini

[pytest]
addopts = --disable-socket

test.py

import asynctest

class TestClass(asynctest.TestCase):
    async def test_something(self):
        pass

commands to enter:

pip install pytest pytest-socket asynctest
pytest test.py

Unexpected interaction between --allowed_hosts and enable_socket()

I have the following general setting:

[pytest]
addopts = --allow-hosts=127.0.0.1,::1

and socket_enabled() (or passing the fixture) to a specific test errors at the connection level. The _true_socket is restored, but the connection is not:

inst = <socket.socket fd=21, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('0.0.0.0', 0)>, args = (('***.***.42.194', 443),), host = '***.***.42.194'

    def guarded_connect(inst, *args):
        host = host_from_connect_args(args)
        if host and host in allowed:
            return _true_connect(inst, *args)
>       raise SocketConnectBlockedError(allowed, host)
E       Failed to send request: A test tried to use socket.socket.connect() with host "***.***.42.194" (allowed: "127.0.0.1,::1").

If I am explicitly enabling the socket for a test I expected it to override the allowed_hosts.

Adding remove_host_restrictions() inside the specific test restores the _true_connect and allows the test to run.

Maybe enable_socket should be:

def enable_socket():
    """ re-enable socket.socket to enable the Internet. useful in testing.
    """
    socket.socket = _true_socket
    socket.socket.connect = _true_connect

Notice the socket.socket.connect = _true_connect. This is also probably what happens with issue #15

`remove_host_restrictions` functionality no longer in the public interface

Hi there!

First of all, thank you for your work writing and maintaining this package. My team is using the package to limit connections to the outside world by default for all unit tests but then enable outside access for a handful of integration tests. We use a yield fixture with version 0.4.1 to do this:

@pytest.fixture
def enable_network_requests():
    remove_host_restrictions()
    yield
    socket_allow_hosts(["127.0.0.1", MOTO_RESOURCE_ADDRESS])

I tried updating to 0.5.0 but see that remove_host_restrictions is no longer in the public interface. Is there a possibility to bring it back or perhaps some other method I'm missing? Thanks!

socket_enabled does not completely enable socket

When I do:

import requests
from pytest import fixture


@fixture
def my_fixture():
    requests.get("https://google.com")


def test_abc(my_fixture, socket_enabled):
    assert True

I expect socket_enabled to completely enable calls to socket. However, this currently fails in the fixture.

Same if I do:

def r():
    requests.get("https://google.com")
    return True


def test_def(socket_enabled):
    assert r()

And same if I use @pytest.mark.enable_socket.

My setup.cfg:

[tool:pytest]
addopts = --allow-hosts=127.0.0.1

sockets still blocked when --disable-socket is not used

I tried to integrate pytest-socket in my project.
It works mostly fine for the cases that I want sockets disabled by passing --disable-socket in the option.

However, when I want to run the entire test suite normally with network, i.e., without passing --disable-socket, somehow the plugin incorrectly blocks sockets, raising error:

>       raise SocketBlockedError()
E       pytest_socket.SocketBlockedError: A test tried to use socket.socket.

An example from CI results:
https://github.com/orionlee/lightkurve/runs/2612809173?check_suite_focus=true

The project in question uses a variety of popular scientific computing and astronomy packages.

Unfortunately, I cannot yet reproduce it in an isolated setup. I'm still submitting this issue to see if you have any inklings on what's going on.

What I've tried so far:

Environments:

  • pytest-socket version: 0.4.0
  • OS: both Windows on Linux
  • python: 3.7, 3.8
  • pytest: 6.2.3
  • pytest plugins used:
    plugins: cov-2.10.1, doctestplus-0.8.0, remotedata-0.3.2, forked-1.3.0, socket-0.4.0, xdist-2.2.1

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: Cannot find preset's package (github>whitesource/merge-confidence:beta)

pytest-socket raises IndexError when used with httpx

pytest-socket raises IndexError when used with httpx:

cls = <class 'pytest_socket.disable_socket.<locals>.GuardedSocket'>, args = ()
kwargs = {'family': <AddressFamily.AF_INET: 2>, 'proto': 6, 'type': <SocketKind.SOCK_STREAM: 1>}

    def __new__(cls, *args, **kwargs):
        try:
>           is_unix_socket = args[0] == socket.AF_UNIX
E           IndexError: tuple index out of range

.venv/lib/python3.9/site-packages/pytest_socket.py:89: IndexError
See full stack trace
.venv/lib/python3.9/site-packages/httpx/_client.py:1736: in get
    return await self.request(
.venv/lib/python3.9/site-packages/httpx/_client.py:1513: in request
    return await self.send(request, auth=auth, follow_redirects=follow_redirects)
.venv/lib/python3.9/site-packages/httpx/_client.py:1600: in send
    response = await self._send_handling_auth(
.venv/lib/python3.9/site-packages/httpx/_client.py:1628: in _send_handling_auth
    response = await self._send_handling_redirects(
.venv/lib/python3.9/site-packages/httpx/_client.py:1665: in _send_handling_redirects
    response = await self._send_single_request(request)
.venv/lib/python3.9/site-packages/httpx/_client.py:1702: in _send_single_request
    response = await transport.handle_async_request(request)
.venv/lib/python3.9/site-packages/httpx/_transports/asgi.py:152: in handle_async_request
    await self.app(scope, receive, send)
...
.venv/lib/python3.9/site-packages/httpx/_client.py:1513: in request
    return await self.send(request, auth=auth, follow_redirects=follow_redirects)
.venv/lib/python3.9/site-packages/httpx/_client.py:1600: in send
    response = await self._send_handling_auth(
.venv/lib/python3.9/site-packages/httpx/_client.py:1628: in _send_handling_auth
    response = await self._send_handling_redirects(
.venv/lib/python3.9/site-packages/httpx/_client.py:1665: in _send_handling_redirects
    response = await self._send_single_request(request)
.venv/lib/python3.9/site-packages/httpx/_client.py:1702: in _send_single_request
    response = await transport.handle_async_request(request)
.venv/lib/python3.9/site-packages/httpx/_transports/default.py:291: in handle_async_request
    resp = await self._pool.handle_async_request(req)
.venv/lib/python3.9/site-packages/httpcore/_async/connection_pool.py:248: in handle_async_request
    raise exc
.venv/lib/python3.9/site-packages/httpcore/_async/connection_pool.py:232: in handle_async_request
    response = await connection.handle_async_request(request)
.venv/lib/python3.9/site-packages/httpcore/_async/connection.py:90: in handle_async_request
    raise exc
.venv/lib/python3.9/site-packages/httpcore/_async/connection.py:67: in handle_async_request
    stream = await self._connect(request)
.venv/lib/python3.9/site-packages/httpcore/_async/connection.py:115: in _connect
    stream = await self._network_backend.connect_tcp(**kwargs)
.venv/lib/python3.9/site-packages/httpcore/backends/auto.py:23: in connect_tcp
    return await self._backend.connect_tcp(
.venv/lib/python3.9/site-packages/httpcore/backends/asyncio.py:97: in connect_tcp
    stream: anyio.abc.ByteStream = await anyio.connect_tcp(
.venv/lib/python3.9/site-packages/anyio/_core/_sockets.py:180: in connect_tcp
    await event.wait()
.venv/lib/python3.9/site-packages/anyio/_backends/_asyncio.py:567: in __aexit__
    raise exceptions[0]
.venv/lib/python3.9/site-packages/anyio/_core/_sockets.py:127: in try_connect
    stream = await asynclib.connect_tcp(remote_host, remote_port, local_address)
.venv/lib/python3.9/site-packages/anyio/_backends/_asyncio.py:1499: in connect_tcp
    await get_running_loop().create_connection(StreamProtocol, host, port,
/usr/lib/python3.9/asyncio/base_events.py:1041: in create_connection
    sock = await self._connect_sock(
/usr/lib/python3.9/asyncio/base_events.py:938: in _connect_sock
    sock = socket.socket(family=family, type=type_, proto=proto)

I'm not sure exactly why this happens but I'm guessing it is somehow related to anyio rather than httpx. You can reproduce the issue with this code:

import pytest
import httpx


@pytest.fixture(autouse=True)
def anyio_backend():
    return "asyncio"

async def test_httpx():
    async with httpx.AsyncClient() as client:
        await client.get("http://www.example.com/")

Issue with sockets when trying to run Home Assistant tests

Hi,

Posting this issue here as it's related to this repo:

Running pytest . on this repo:
https://github.com/mrtolkien/hass-nature-remo

Logs are the following:

./tests/test_api.py::test_get_appliances[pyloop] Failed: [undefined]pytest_socket.SocketConnectBlockedError: A test tried to use socket.socket.connect() with host "15.197.175.142" (allowed: "127.0.0.1").
hass = <homeassistant.core.HomeAssistant object at 0x7f46905c1db0>
socket_enabled = None

    @pytest.mark.enable_socket()
    async def test_get_appliances(hass, socket_enabled):
        api = NatureRemoAPI(
            os.environ[tests.access_token_field],
            async_get_clientsession(hass),
        )
    
>       devices = await api.get_devices()

tests/test_api.py:18: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
custom_components/nature_remo/api/nature_remo_api.py:43: in get_devices
    devices_response = await devices_query
../../../.cache/pypoetry/virtualenvs/home-assistant-nature-remo-Aj4ZNfxY-py3.10/lib/python3.10/site-packages/aiohttp/client.py:520: in _request
    conn = await self._connector.connect(
../../../.cache/pypoetry/virtualenvs/home-assistant-nature-remo-Aj4ZNfxY-py3.10/lib/python3.10/site-packages/aiohttp/connector.py:535: in connect
    proto = await self._create_connection(req, traces, timeout)
../../../.cache/pypoetry/virtualenvs/home-assistant-nature-remo-Aj4ZNfxY-py3.10/lib/python3.10/site-packages/aiohttp/connector.py:892: in _create_connection
    _, proto = await self._create_direct_connection(req, traces, timeout)
../../../.cache/pypoetry/virtualenvs/home-assistant-nature-remo-Aj4ZNfxY-py3.10/lib/python3.10/site-packages/aiohttp/connector.py:1020: in _create_direct_connection
    transp, proto = await self._wrap_create_connection(
../../../.cache/pypoetry/virtualenvs/home-assistant-nature-remo-Aj4ZNfxY-py3.10/lib/python3.10/site-packages/aiohttp/connector.py:969: in _wrap_create_connection
    return await self._loop.create_connection(*args, **kwargs)  # type: ignore  # noqa
../../../.pyenv/versions/3.10.1/lib/python3.10/asyncio/base_events.py:1040: in create_connection
    sock = await self._connect_sock(
../../../.pyenv/versions/3.10.1/lib/python3.10/asyncio/base_events.py:954: in _connect_sock
    await self.sock_connect(sock, address)
../../../.pyenv/versions/3.10.1/lib/python3.10/asyncio/selector_events.py:502: in sock_connect
    return await fut
../../../.pyenv/versions/3.10.1/lib/python3.10/asyncio/selector_events.py:507: in _sock_connect
    sock.connect(address)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

inst = <socket.socket [closed] fd=-1, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6>
args = (('15.197.175.142', 443),), host = '15.197.175.142'

    def guarded_connect(inst, *args):
        host = host_from_connect_args(args)
        if host and host in allowed:
            return _true_connect(inst, *args)
>       raise SocketConnectBlockedError(allowed, host)
E       pytest_socket.SocketConnectBlockedError: A test tried to use socket.socket.connect() with host "15.197.175.142" (allowed: "127.0.0.1").

../../../.cache/pypoetry/virtualenvs/home-assistant-nature-remo-Aj4ZNfxY-py3.10/lib/python3.10/site-packages/pytest_socket.py:154: SocketConnectBlockedError

It seems that by default sockets and hosts are all disabled for the tests there. I have tried adding adopts = --allow-unix-socket --allow-hosts=15.197.175.142 to pytest.ini, and the mark @pytest.mark.enable_socket(), to no avail.

Any clue about what I should change to let pytest use sockets?

Replace pytest-flake8 with a pre-commit hook

At some point, pytest and flake8 stopped working well together. See tholo/pytest-flake8#81 and related links.

This may get worse with pytest 7

On this thread, see a comment around running flake8 as part of pytest is considered an anti pattern.

I think that the more tooling we try to bake into a given pytest run, the harder it is to split them apart, so instead, let's adopt the pre-commit framework for executing any stylistic checks we want prior to a commit - flake8, black, isort, and anything else we want, like editorconfig...

This check would need to also run on CI so that if an author doesn't run it locally, it'll catch anything missing.

Scopes "module" or "class" circumvent the blocking

Thanks for the great plugin!

I noticed the following:

Example 1:

import requests

def test():
    requests.get("http://httpbin.org/status/200")

This will raise SocketBlockedError, as expected.

Example 2:

import pytest
import requests

@pytest.fixture # scope == "function" by default
def getit():
    requests.get("http://httpbin.org/status/200")

def test(getit):
    pass

This will also raise the SocketBlockedError. Also as expected.

Example 3:

import pytest
import requests

@pytest.fixture(scope="module") # <== Notice the different scope!
def getit():
    requests.get("http://httpbin.org/status/200")

def test(getit):
    pass

This will pass. No exception.

To me, this was unexpected and lead to some debugging headaches.

Is this intended behavior or a bug? Is there a way to make the plugin also prevent cases such as this one?

0.4.0: tests currently failing (easy fixes)

As noted in #68, I'm working on/trying to package pytest-socket for my OS's repositories. In doing so, I opened #69, but I'm also noticing that tests seem to be failing out of the box on the downloaded archive. Here are the steps I took:

  • download and extract the (currently released) archive from GitHub (not PyPI, because those don't include the tests--see #68): curl -L https://github.com/miketheman/pytest-socket/archive/refs/tags/0.4.0.tar.gz | tar -xzv
  • modify pyproject.toml configuration to include tests in sdist, per #69, then build sdist archive with poetry build -f sdist.
  • extract and enter the sdist archive: `tar -xzvf dist/pytest-socket-0.4.0.tar.gz; cd pytest-socket-0.4.0'
  • build egg_info contents in order to allow pytest to detect it as a plugin: python setup.py egg_info
  • run tests: python -m pytest.

Fixes

The causes seem to be fairly simple:

  • requests is used in some of the tests but not specified as a test/dev dependency. Installing requests fixes one of the issues.

  • Several of the source files have lines that are too long & other formatting errors, therefore breaking the flake8 checks (E501 line too long, E122 missing continuation indent). Easy fixes would be either specifying in pytest.ini

    flake8-ignore =
        * E501
        * E122
    

    or reformatting the source files to obey the style rules, e.g. using black.

Side notes

  • Building the sdist, rather than simply running tests from the original source worktree, is important because we want to (1) replicate the environment of the actual archive distributed on PyPI, and (2) because we need to use setup.py to build the egg_info for testing (otherwise we would need to install the package in order to test it, which is not really a great way to test things--unless I'm missing something; do you do testing some other way?).
  • We need to run python -m pytest instead of simply pytest in order for the current library to be included in the Python library search path; this is a quirk of how python -m works in contrast to simply calling an executable and is a very common pytest issue.

Full failure log

==================== test session starts =====================
platform linux -- Python 3.9.6, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: /home/kshi/pt/pytest-socket-0.4.0, configfile: pytest.ini
plugins: socket-0.4.0, anyio-3.3.0, httpbin-1.0.0, cov-2.12.1, flake8-1.0.7
collected 47 items

pytest_socket.py F                                     [  2%]
setup.py F                                             [  4%]
tests/conftest.py s                                    [  6%]
tests/test_async.py F.F                                [ 12%]
tests/test_restrict_hosts.py F.......................  [ 63%]
tests/test_socket.py F................                 [100%]

========================== FAILURES ==========================
________________________ FLAKE8-check ________________________
/home/kshi/pt/pytest-socket-0.4.0/pytest_socket.py:11:80: E501 line too long (86 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/pytest_socket.py:19:80: E501 line too long (113 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/pytest_socket.py:35:80: E501 line too long (86 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/pytest_socket.py:91:80: E501 line too long (85 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/pytest_socket.py:109:80: E501 line too long (106 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/pytest_socket.py:110:80: E501 line too long (104 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/pytest_socket.py:111:80: E501 line too long (115 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/pytest_socket.py:160:80: E501 line too long (87 > 79 characters)

--------------------- Captured log call ----------------------
WARNING  flake8.options.manager:manager.py:186 option --indent-size: please update `help=` text to use %(default)s instead of %default -- this will be an error in the future
WARNING  flake8.options.manager:manager.py:207 option --max-complexity: please update from optparse string `type=` to argparse callable `type=` -- this will be an error in the future
________________________ FLAKE8-check ________________________
/home/kshi/pt/pytest-socket-0.4.0/setup.py:5:1: E122 continuation line missing indentation or outdented
/home/kshi/pt/pytest-socket-0.4.0/setup.py:7:1: E122 continuation line missing indentation or outdented
/home/kshi/pt/pytest-socket-0.4.0/setup.py:10:1: E122 continuation line missing indentation or outdented
/home/kshi/pt/pytest-socket-0.4.0/setup.py:16:80: E501 line too long (4863 > 79 characters)

--------------------- Captured log call ----------------------
WARNING  flake8.options.manager:manager.py:186 option --indent-size: please update `help=` text to use %(default)s instead of %default -- this will be an error in the future
WARNING  flake8.options.manager:manager.py:207 option --max-complexity: please update from optparse string `type=` to argparse callable `type=` -- this will be an error in the future
________________________ FLAKE8-check ________________________
/home/kshi/pt/pytest-socket-0.4.0/tests/test_async.py:28:80: E501 line too long (86 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_async.py:55:80: E501 line too long (86 > 79 characters)

--------------------- Captured log call ----------------------
WARNING  flake8.options.manager:manager.py:186 option --indent-size: please update `help=` text to use %(default)s instead of %default -- this will be an error in the future
WARNING  flake8.options.manager:manager.py:207 option --max-complexity: please update from optparse string `type=` to argparse callable `type=` -- this will be an error in the future
_______________________ test_starlette _______________________

testdir = <Testdir local('/tmp/pytest-of-kshi/pytest-26/test_starlette0')>

    @unix_sockets_only
    def test_starlette(testdir):
        testdir.makepyfile("""
            from pytest_socket import disable_socket
            from starlette.responses import HTMLResponse
            from starlette.testclient import TestClient


            def pytest_runtest_setup():
                disable_socket()


            async def app(scope, receive, send):
                assert scope['type'] == 'http'
                response = HTMLResponse('<html><body>Hello, world!</body></html>')
                await response(scope, receive, send)


            def test_app():
                client = TestClient(app)
                response = client.get('/')
                assert response.status_code == 200
        """)
        result = testdir.runpytest("--verbose", "--disable-socket", "--allow-unix-socket")
>       result.assert_outcomes(passed=1, skipped=0, failed=0)
E       AssertionError: assert {'errors': 1,...pped': 0, ...} == {'errors': 0,...pped': 0, ...}
E         Omitting 4 identical items, use -vv to show
E         Differing items:
E         {'errors': 1} != {'errors': 0}
E         {'passed': 0} != {'passed': 1}
E         Use -v to get the full diff

/home/kshi/pytest-socket-0.4.0/tests/test_async.py:56: AssertionError
-------------------- Captured stdout call --------------------
============================= test session starts ==============================
platform linux -- Python 3.9.6, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- /home/kshi/.venv/bin/python
cachedir: .pytest_cache
rootdir: /tmp/pytest-of-kshi/pytest-26/test_starlette0
plugins: socket-0.4.0, anyio-3.3.0, httpbin-1.0.0, cov-2.12.1, flake8-1.0.7
collecting ... collected 0 items / 1 error

==================================== ERRORS ====================================
______________________ ERROR collecting test_starlette.py ______________________
ImportError while importing test module '/tmp/pytest-of-kshi/pytest-26/test_starlette0/test_starlette.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.9/importlib/__init__.py:127: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
test_starlette.py:3: in <module>
    from starlette.testclient import TestClient
/home/kshi/.venv/lib/python3.9/site-packages/starlette/testclient.py:16: in <module>
    import requests
E   ModuleNotFoundError: No module named 'requests'
=========================== short test summary info ============================
ERROR test_starlette.py
!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
=============================== 1 error in 0.13s ===============================
________________________ FLAKE8-check ________________________
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:27:80: E501 line too long (90 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:44:80: E501 line too long (109 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:63:80: E501 line too long (87 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:64:80: E501 line too long (86 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:68:80: E501 line too long (88 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:97:80: E501 line too long (101 > 79 characters)
/home/kshi/pt/pytes```
==================== test session starts =====================
platform linux -- Python 3.9.6, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: /home/kshi/pt/pytest-socket-0.4.0, configfile: pytest.ini
plugins: socket-0.4.0, anyio-3.3.0, httpbin-1.0.0, cov-2.12.1, flake8-1.0.7
collected 47 items

pytest_socket.py F                                     [  2%]
setup.py F                                             [  4%]
tests/conftest.py s                                    [  6%]
tests/test_async.py F.F                                [ 12%]
tests/test_restrict_hosts.py F.......................  [ 63%]
tests/test_socket.py F................                 [100%]

========================== FAILURES ==========================
________________________ FLAKE8-check ________________________
/home/kshi/pt/pytest-socket-0.4.0/pytest_socket.py:11:80: E501 line too long (86 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/pytest_socket.py:19:80: E501 line too long (113 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/pytest_socket.py:35:80: E501 line too long (86 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/pytest_socket.py:91:80: E501 line too long (85 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/pytest_socket.py:109:80: E501 line too long (106 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/pytest_socket.py:110:80: E501 line too long (104 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/pytest_socket.py:111:80: E501 line too long (115 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/pytest_socket.py:160:80: E501 line too long (87 > 79 characters)

--------------------- Captured log call ----------------------
WARNING  flake8.options.manager:manager.py:186 option --indent-size: please update `help=` text to use %(default)s instead of %default -- this will be an error in the future
WARNING  flake8.options.manager:manager.py:207 option --max-complexity: please update from optparse string `type=` to argparse callable `type=` -- this will be an error in the future
________________________ FLAKE8-check ________________________
/home/kshi/pt/pytest-socket-0.4.0/setup.py:5:1: E122 continuation line missing indentation or outdented
/home/kshi/pt/pytest-socket-0.4.0/setup.py:7:1: E122 continuation line missing indentation or outdented
/home/kshi/pt/pytest-socket-0.4.0/setup.py:10:1: E122 continuation line missing indentation or outdented
/home/kshi/pt/pytest-socket-0.4.0/setup.py:16:80: E501 line too long (4863 > 79 characters)

--------------------- Captured log call ----------------------
WARNING  flake8.options.manager:manager.py:186 option --indent-size: please update `help=` text to use %(default)s instead of %default -- this will be an error in the future
WARNING  flake8.options.manager:manager.py:207 option --max-complexity: please update from optparse string `type=` to argparse callable `type=` -- this will be an error in the future
________________________ FLAKE8-check ________________________
/home/kshi/pt/pytest-socket-0.4.0/tests/test_async.py:28:80: E501 line too long (86 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_async.py:55:80: E501 line too long (86 > 79 characters)

--------------------- Captured log call ----------------------
WARNING  flake8.options.manager:manager.py:186 option --indent-size: please update `help=` text to use %(default)s instead of %default -- this will be an error in the future
WARNING  flake8.options.manager:manager.py:207 option --max-complexity: please update from optparse string `type=` to argparse callable `type=` -- this will be an error in the future
_______________________ test_starlette _______________________

testdir = <Testdir local('/tmp/pytest-of-kshi/pytest-26/test_starlette0')>

    @unix_sockets_only
    def test_starlette(testdir):
        testdir.makepyfile("""
            from pytest_socket import disable_socket
            from starlette.responses import HTMLResponse
            from starlette.testclient import TestClient


            def pytest_runtest_setup():
                disable_socket()


            async def app(scope, receive, send):
                assert scope['type'] == 'http'
                response = HTMLResponse('<html><body>Hello, world!</body></html>')
                await response(scope, receive, send)


            def test_app():
                client = TestClient(app)
                response = client.get('/')
                assert response.status_code == 200
        """)
        result = testdir.runpytest("--verbose", "--disable-socket", "--allow-unix-socket")
>       result.assert_outcomes(passed=1, skipped=0, failed=0)
E       AssertionError: assert {'errors': 1,...pped': 0, ...} == {'errors': 0,...pped': 0, ...}
E         Omitting 4 identical items, use -vv to show
E         Differing items:
E         {'errors': 1} != {'errors': 0}
E         {'passed': 0} != {'passed': 1}
E         Use -v to get the full diff

/home/kshi/pytest-socket-0.4.0/tests/test_async.py:56: AssertionError
-------------------- Captured stdout call --------------------
============================= test session starts ==============================
platform linux -- Python 3.9.6, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- /home/kshi/.venv/bin/python
cachedir: .pytest_cache
rootdir: /tmp/pytest-of-kshi/pytest-26/test_starlette0
plugins: socket-0.4.0, anyio-3.3.0, httpbin-1.0.0, cov-2.12.1, flake8-1.0.7
collecting ... collected 0 items / 1 error

==================================== ERRORS ====================================
______________________ ERROR collecting test_starlette.py ______________________
ImportError while importing test module '/tmp/pytest-of-kshi/pytest-26/test_starlette0/test_starlette.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.9/importlib/__init__.py:127: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
test_starlette.py:3: in <module>
    from starlette.testclient import TestClient
/home/kshi/.venv/lib/python3.9/site-packages/starlette/testclient.py:16: in <module>
    import requests
E   ModuleNotFoundError: No module named 'requests'
=========================== short test summary info ============================
ERROR test_starlette.py
!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
=============================== 1 error in 0.13s ===============================
________________________ FLAKE8-check ________________________
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:27:80: E501 line too long (90 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:44:80: E501 line too long (109 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:63:80: E501 line too long (87 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:64:80: E501 line too long (86 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:68:80: E501 line too long (88 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:97:80: E501 line too long (101 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:110:80: E501 line too long (88 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:134:80: E501 line too long (89 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:162:80: E501 line too long (93 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:166:80: E501 line too long (94 > 79 characters)

--------------------- Captured log call ----------------------
WARNING  flake8.options.manager:manager.py:186 option --indent-size: please update `help=` text to use %(default)s instead of %default -- this will be an error in the future
WARNING  flake8.options.manager:manager.py:207 option --max-complexity: please update from optparse string `type=` to argparse callable `type=` -- this will be an error in the future
________________________ FLAKE8-check ________________________
/home/kshi/pt/pytest-socket-0.4.0/tests/test_socket.py:234:80: E501 line too long (109 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_socket.py:246:80: E501 line too long (109 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_socket.py:256:80: E501 line too long (86 > 79 characters)

--------------------- Captured log call ----------------------
WARNING  flake8.options.manager:manager.py:186 option --indent-size: please update `help=` text to use %(default)s instead of %default -- this will be an error in the future
WARNING  flake8.options.manager:manager.py:207 option --max-complexity: please update from optparse string `type=` to argparse callable `type=` -- this will be an error in the future

----------- coverage: platform linux, python 3.9.6-final-0 -----------
Name               Stmts   Miss  Cover
--------------------------------------
pytest_socket.py      86     26    70%
--------------------------------------
TOTAL                 86     26    70%

================== short test summary info ===================
FAILED pytest_socket.py::FLAKE8
FAILED setup.py::F```
==================== test session starts =====================
platform linux -- Python 3.9.6, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: /home/kshi/pt/pytest-socket-0.4.0, configfile: pytest.ini
plugins: socket-0.4.0, anyio-3.3.0, httpbin-1.0.0, cov-2.12.1, flake8-1.0.7
collected 47 items

pytest_socket.py F                                     [  2%]
setup.py F                                             [  4%]
tests/conftest.py s                                    [  6%]
tests/test_async.py F.F                                [ 12%]
tests/test_restrict_hosts.py F.......................  [ 63%]
tests/test_socket.py F................                 [100%]

========================== FAILURES ==========================
________________________ FLAKE8-check ________________________
/home/kshi/pt/pytest-socket-0.4.0/pytest_socket.py:11:80: E501 line too long (86 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/pytest_socket.py:19:80: E501 line too long (113 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/pytest_socket.py:35:80: E501 line too long (86 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/pytest_socket.py:91:80: E501 line too long (85 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/pytest_socket.py:109:80: E501 line too long (106 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/pytest_socket.py:110:80: E501 line too long (104 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/pytest_socket.py:111:80: E501 line too long (115 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/pytest_socket.py:160:80: E501 line too long (87 > 79 characters)

--------------------- Captured log call ----------------------
WARNING  flake8.options.manager:manager.py:186 option --indent-size: please update `help=` text to use %(default)s instead of %default -- this will be an error in the future
WARNING  flake8.options.manager:manager.py:207 option --max-complexity: please update from optparse string `type=` to argparse callable `type=` -- this will be an error in the future
________________________ FLAKE8-check ________________________
/home/kshi/pt/pytest-socket-0.4.0/setup.py:5:1: E122 continuation line missing indentation or outdented
/home/kshi/pt/pytest-socket-0.4.0/setup.py:7:1: E122 continuation line missing indentation or outdented
/home/kshi/pt/pytest-socket-0.4.0/setup.py:10:1: E122 continuation line missing indentation or outdented
/home/kshi/pt/pytest-socket-0.4.0/setup.py:16:80: E501 line too long (4863 > 79 characters)

--------------------- Captured log call ----------------------
WARNING  flake8.options.manager:manager.py:186 option --indent-size: please update `help=` text to use %(default)s instead of %default -- this will be an error in the future
WARNING  flake8.options.manager:manager.py:207 option --max-complexity: please update from optparse string `type=` to argparse callable `type=` -- this will be an error in the future
________________________ FLAKE8-check ________________________
/home/kshi/pt/pytest-socket-0.4.0/tests/test_async.py:28:80: E501 line too long (86 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_async.py:55:80: E501 line too long (86 > 79 characters)

--------------------- Captured log call ----------------------
WARNING  flake8.options.manager:manager.py:186 option --indent-size: please update `help=` text to use %(default)s instead of %default -- this will be an error in the future
WARNING  flake8.options.manager:manager.py:207 option --max-complexity: please update from optparse string `type=` to argparse callable `type=` -- this will be an error in the future
_______________________ test_starlette _______________________

testdir = <Testdir local('/tmp/pytest-of-kshi/pytest-26/test_starlette0')>

    @unix_sockets_only
    def test_starlette(testdir):
        testdir.makepyfile("""
            from pytest_socket import disable_socket
            from starlette.responses import HTMLResponse
            from starlette.testclient import TestClient


            def pytest_runtest_setup():
                disable_socket()


            async def app(scope, receive, send):
                assert scope['type'] == 'http'
                response = HTMLResponse('<html><body>Hello, world!</body></html>')
                await response(scope, receive, send)


            def test_app():
                client = TestClient(app)
                response = client.get('/')
                assert response.status_code == 200
        """)
        result = testdir.runpytest("--verbose", "--disable-socket", "--allow-unix-socket")
>       result.assert_outcomes(passed=1, skipped=0, failed=0)
E       AssertionError: assert {'errors': 1,...pped': 0, ...} == {'errors': 0,...pped': 0, ...}
E         Omitting 4 identical items, use -vv to show
E         Differing items:
E         {'errors': 1} != {'errors': 0}
E         {'passed': 0} != {'passed': 1}
E         Use -v to get the full diff

/home/kshi/pytest-socket-0.4.0/tests/test_async.py:56: AssertionError
-------------------- Captured stdout call --------------------
============================= test session starts ==============================
platform linux -- Python 3.9.6, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- /home/kshi/.venv/bin/python
cachedir: .pytest_cache
rootdir: /tmp/pytest-of-kshi/pytest-26/test_starlette0
plugins: socket-0.4.0, anyio-3.3.0, httpbin-1.0.0, cov-2.12.1, flake8-1.0.7
collecting ... collected 0 items / 1 error

==================================== ERRORS ====================================
______________________ ERROR collecting test_starlette.py ______________________
ImportError while importing test module '/tmp/pytest-of-kshi/pytest-26/test_starlette0/test_starlette.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.9/importlib/__init__.py:127: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
test_starlette.py:3: in <module>
    from starlette.testclient import TestClient
/home/kshi/.venv/lib/python3.9/site-packages/starlette/testclient.py:16: in <module>
    import requests
E   ModuleNotFoundError: No module named 'requests'
=========================== short test summary info ============================
ERROR test_starlette.py
!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
=============================== 1 error in 0.13s ===============================
________________________ FLAKE8-check ________________________
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:27:80: E501 line too long (90 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:44:80: E501 line too long (109 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:63:80: E501 line too long (87 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:64:80: E501 line too long (86 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:68:80: E501 line too long (88 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:97:80: E501 line too long (101 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:110:80: E501 line too long (88 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:134:80: E501 line too long (89 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:162:80: E501 line too long (93 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:166:80: E501 line too long (94 > 79 characters)

--------------------- Captured log call ----------------------
WARNING  flake8.options.manager:manager.py:186 option --indent-size: please update `help=` text to use %(default)s instead of %default -- this will be an error in the future
WARNING  flake8.options.manager:manager.py:207 option --max-complexity: please update from optparse string `type=` to argparse callable `type=` -- this will be an error in the future
________________________ FLAKE8-check ________________________
/home/kshi/pt/pytest-socket-0.4.0/tests/test_socket.py:234:80: E501 line too long (109 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_socket.py:246:80: E501 line too long (109 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_socket.py:256:80: E501 line too long (86 > 79 characters)

--------------------- Captured log call ----------------------
WARNING  flake8.options.manager:manager.py:186 option --indent-size: please update `help=` text to use %(default)s instead of %default -- this will be an error in the future
WARNING  flake8.options.manager:manager.py:207 option --max-complexity: please update from optparse string `type=` to argparse callable `type=` -- this will be an error in the future

----------- coverage: platform linux, python 3.9.6-final-0 -----------
Name               Stmts   Miss  Cover
--------------------------------------
pytest_socket.py      86     26    70%
--------------------------------------
TOTAL                 86     26    70%

================== short test summary info ===================
FAILED pytest_socket.py::FLAKE8
FAILED setup.py::FLAKE8
FAILED tests/test_async.py::FLAKE8
FAILED tests/test_async.py::test_starlette - AssertionError...
FAILED tests/test_restrict_hosts.py::FLAKE8
FAILED tests/test_socket.py::FLAKE8
========== 6 failed, 40 passed, 1 skipped in 6.44s ===========
```LAKE8
FAILED tests/test_async.py::FLAKE8
FAILED tests/test_async.py::test_starlette - AssertionError...
FAILED tests/test_restrict_hosts.py::FLAKE8
FAILED tests/test_socket.py::FLAKE8
========== 6 failed, 40 passed, 1 skipped in 6.44s ===========
```t-socket-0.4.0/tests/test_restrict_hosts.py:110:80: E501 line too long (88 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:134:80: E501 line too long (89 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:162:80: E501 line too long (93 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_restrict_hosts.py:166:80: E501 line too long (94 > 79 characters)

--------------------- Captured log call ----------------------
WARNING  flake8.options.manager:manager.py:186 option --indent-size: please update `help=` text to use %(default)s instead of %default -- this will be an error in the future
WARNING  flake8.options.manager:manager.py:207 option --max-complexity: please update from optparse string `type=` to argparse callable `type=` -- this will be an error in the future
________________________ FLAKE8-check ________________________
/home/kshi/pt/pytest-socket-0.4.0/tests/test_socket.py:234:80: E501 line too long (109 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_socket.py:246:80: E501 line too long (109 > 79 characters)
/home/kshi/pt/pytest-socket-0.4.0/tests/test_socket.py:256:80: E501 line too long (86 > 79 characters)

--------------------- Captured log call ----------------------
WARNING  flake8.options.manager:manager.py:186 option --indent-size: please update `help=` text to use %(default)s instead of %default -- this will be an error in the future
WARNING  flake8.options.manager:manager.py:207 option --max-complexity: please update from optparse string `type=` to argparse callable `type=` -- this will be an error in the future

----------- coverage: platform linux, python 3.9.6-final-0 -----------
Name               Stmts   Miss  Cover
--------------------------------------
pytest_socket.py      86     26    70%
--------------------------------------
TOTAL                 86     26    70%

================== short test summary info ===================
FAILED pytest_socket.py::FLAKE8
FAILED setup.py::FLAKE8
FAILED tests/test_async.py::FLAKE8
FAILED tests/test_async.py::test_starlette - AssertionError...
FAILED tests/test_restrict_hosts.py::FLAKE8
FAILED tests/test_socket.py::FLAKE8
========== 6 failed, 40 passed, 1 skipped in 6.44s ===========

sockets still blocked for tests that use bokeh server when exception is specified in command line

For tests that involve creating a bokeh server, if I pass the command line options:

  • --allow-unix-socket and / or,
  • --allow-hosts=127.0.0.1,localhost,::1
    the test still failed complaining that the sockets are blocked.

A workaround: if I mark individual tests with @pytest.mark.enable_socket, then the test will correctly pass.


Example test:

import pytest
import bokeh
from bokeh.io import show, output_notebook, push_notebook
from bokeh.layouts import layout, Spacer
from bokeh.models.widgets import Button, Div


def test_bokeh_server():
    def create_interact_ui(doc):
        widgets_and_figures = layout([Div(text="test bokeh server")])
        doc.add_root(widgets_and_figures)

    output_notebook(verbose=False, hide_banner=True)
    show(create_interact_ui)

If I run the command

> pytest tests/test_bokeh.py  --disable-socket --allow-unix-socket --allow-hosts=127.0.0.1,localhost,::1

The test will fail with the following exception:

tests\test_bokeh.py:16: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
c:\anaconda3\envs\lkv2_dev\lib\site-packages\bokeh\io\showing.py:137: in show
    return run_notebook_hook(state.notebook_type, 'app', obj, state, notebook_url, **kw)
c:\anaconda3\envs\lkv2_dev\lib\site-packages\bokeh\io\notebook.py:298: in run_notebook_hook
    return _HOOKS[notebook_type][action](*args, **kw)
c:\anaconda3\envs\lkv2_dev\lib\site-packages\bokeh\io\notebook.py:467: in show_app
    loop = IOLoop.current()
c:\anaconda3\envs\lkv2_dev\lib\site-packages\tornado\ioloop.py:263: in current
    loop = asyncio.get_event_loop()
c:\anaconda3\envs\lkv2_dev\lib\asyncio\events.py:640: in get_event_loop
    self.set_event_loop(self.new_event_loop())
c:\anaconda3\envs\lkv2_dev\lib\asyncio\events.py:660: in new_event_loop
    return self._loop_factory()
c:\anaconda3\envs\lkv2_dev\lib\asyncio\selector_events.py:60: in __init__
    self._make_self_pipe()
c:\anaconda3\envs\lkv2_dev\lib\asyncio\selector_events.py:107: in _make_self_pipe
    self._ssock, self._csock = socket.socketpair()
c:\anaconda3\envs\lkv2_dev\lib\socket.py:514: in socketpair
    lsock = socket(family, type, proto)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

cls = <class 'pytest_socket.disable_socket.<locals>.GuardedSocket'>, args = (<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_STREAM: 1>, 0)
kwargs = {}, is_unix_socket = False

    def __new__(cls, *args, **kwargs):
        try:
            is_unix_socket = args[0] == socket.AF_UNIX
        except AttributeError:
            # AF_UNIX not supported on Windows https://bugs.python.org/issue33408
            is_unix_socket = False
    
        if is_unix_socket and allow_unix_socket:
            return super().__new__(cls, *args, **kwargs)
    
>       raise SocketBlockedError()
E       pytest_socket.SocketBlockedError: A test tried to use socket.socket.

pytest: 0.4.0
bokeh: 2.2.3
Platform + Python: Windows + Python 3.7. Also seen the same error (in non isolated setup) in Linux + Python 3.6, and OSX + Python 3.8 CI environments.

Does not work with FastAPI/starlette's TestClient

Hi, thank you for this excellent plugin. While it works fine with Flask's test client, the plugin blocks starlette's TestClient (used by FastAPI). Here's a self-contained example that I'd expect to pass with pytest:

from pytest_socket import disable_socket
from starlette.responses import HTMLResponse
from starlette.testclient import TestClient


def pytest_runtest_setup():
    disable_socket()


async def app(scope, receive, send):
    assert scope['type'] == 'http'
    response = HTMLResponse('<html><body>Hello, world!</body></html>')
    await response(scope, receive, send)


def test_app():
    client = TestClient(app)
    response = client.get('/')
    assert response.status_code == 200

The above returns a:

E       pytest_socket.SocketBlockedError: A test tried to use socket.socket

Would it be possible to make this work with FastAPI/Starlette?

Convert readme / changelog from rst to markdown

This project was born in mid-2017, before PEP-566 was adopted, and before the PEP rolled out to be widely-supported.

This causes a barrier to contribution if anyone wants to update the README or CHANGELOG and isn't familiar with reStructuredText. (As of this writing, getting VS Code to work with rst isn't a smooth experience).

Increasingly, tools are supporting markdown, so let's take the plunge and update the two .rst files in this repo to .md

Refs:

Python 2.7/3.4 Support

Following #21 and associated fix in #22 to accommodate a Python 2.7 behavior, I started thinking about when this plugin should stop supporting Python 2.7 / 3.4

According to the https://pythonclock.org/ , support ends at the end of 2019.

pytest has started warning about deprecation:

You are using Python 2.7.15, which will no longer be supported in pytest 5.0

pytest 5.0 is scheduled for sometime mid-2019 - after which the pytest 4.x branch will continue to be supported until mid-2020.

Please use this issue to discuss your use cases and expectations for longer-term support if you're looking for those versions to be supported beyond the runtime and test framework's lifetime.

pytest-socket blocks retrieving other dependencies

Hi,

I am working on adding pytest-socket to our testing suite. We use bazel test to run pytest. However, after including pytest-socket, it seems as if I cannot download other dependencies for my test to run, for example I get the error

WARNING: Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError('<pip._vendor.urllib3.connection.HTTPSConnection object at 0x7fe50b881640>: Failed to establish a new c
onnection: [Errno -3] Temporary failure in name resolution')': /simple/mypy-boto3-ec2/
ERROR: Could not find a version that satisfies the requirement mypy-boto3-ec2==1.17.77

is there a way to whitelist sockets while we are setting up our testing suite, and then block all sockets? thanks!

Appveyor testing has gone awry

Something is amiss with Appveyor testing - it's no longer executing correctly. Likely a mismatch of Python/pip versions.

Restore semblance of sanity by reading test output, evaluate Python version support, upgrade pip where relevant, any other actions?

Unexpected interaction between --disable-socket and --allow-hosts

If both --disable-socket and --allow-hosts=somehost are passed, I would expect all connections to be disabled except for connections to somehost. In other words, allow-hosts should take precedence.

This isn't currently the case. If both are passed, all connections are disabled.

Thoughts on changing this behavior?

plugin broken by pytest 4.1

    @pytest.fixture(autouse=True)
    def _socket_marker(request):
>       if request.node.get_marker('disable_socket'):
E       AttributeError: 'TestCaseFunction' object has no attribute 'get_marker'

Initial Update

Hi ๐Ÿ‘Š

This is my first visit to this fine repo, but it seems you have been working hard to keep all dependencies updated so far.

Once you have closed this issue, I'll create separate pull requests for every update as soon as I find one.

That's it for now!

Happy merging! ๐Ÿค–

Feature request: Also block DNS lookups (socket.getaddrinfo)

Thank you for this plugin, which helps keep our tests fast and safe! One piece of information that can still leak out even when using it, though, is DNS lookups. It would be great if we could also block calls to socket.getaddrinfo in the same way.

I believe this can be done in a basic way by adding socket.getaddrinfo = guarded to the disable_socket() method here:

def disable_socket():
""" disable socket.socket to disable the Internet. useful in testing.
"""
def guarded(*args, **kwargs):
raise SocketBlockedError()
socket.socket = guarded

...and perhaps updating the exception message to not specifically reference socket.socket.

I have not sent a PR for this because I don't know the pytest API well enough to understand how and when disable_socket is getting called, or how this should interact with socket_allow_hosts() further down โ€” but if that's not a concern, I'd be happy to submit that change for consideration.

Thanks again!

Ability to block by socket number ?

Hi,
Is it possible to extend this so it can enable/disable by socket number(s) ?

(And if not, then this is a feature request, for the same)

Cheers

Include tests in PyPI tarball

Currently, the PyPI source archive does not contain the tests for pytest-socket:

> curl -fsSL 'https://files.pythonhosted.org/packages/source/p/pytest-socket/pytest-socket-0.4.0.tar.gz' | tar -tz
pytest-socket-0.4.0/LICENSE
pytest-socket-0.4.0/README.md
pytest-socket-0.4.0/pyproject.toml
pytest-socket-0.4.0/pytest_socket.py
pytest-socket-0.4.0/setup.py
pytest-socket-0.4.0/PKG-INFO

OS/distribution package vendors rely on package tests to validate sanity/functionality of packages; as such, it would be a good idea to ship these tests together with the rest of the source. It can be done by adding the following line to pyproject.toml (documentation here):

include = [{ path = "tests", format = "sdist" }]

Allow private networks only

Not sure if feature request or documentation clarification if the feature already exists.

It would be nice to allow local network ip addresses to succeed and reject public networks, i.e. ip_address(ip).is_private is True. This is useful when tests make requests to other docker containers on the local network with variable ip addresses but we still do not want requests going to the outside world.

Any clarification or follow up would be great thanks!

Drop support for Python 3.5

Python 3.5 ended support in September 2020.

Tools like pip and poetry will be dropping support for 3.5 soon.

py27 unicode hostname fails allowed-hosts check

If you try and connect with a unicode hostname in python 2:

socket.connect((u'127.0.0.1', 51999))

you get:

SocketConnectBlockedError: A test tried to use socket.socket.connect() with host "None" (allowed: "127.0.0.1,::1").

even if it's in the allowed hosts whitelist

0.3.0: 'TestCaseFunction' object has no attribute 'get_closest_marker'

I noticed an error from the 0.3.0 update on one of my CI jobs:

    def pytest_runtest_setup(item):
>       mark_restrictions = item.get_closest_marker('allow_hosts')
E       AttributeError: 'TestCaseFunction' object has no attribute 'get_closest_marker'
../../../virtualenv/python3.6.3/lib/python3.6/site-packages/pytest_socket.py:90: AttributeError

kevinkjt2000/bowser#165
https://travis-ci.org/kevinkjt2000/bowser/builds/404137945

Are there breaking changes that would cause this?

socket_enabled does not work with pytest.mark.parametrize

When I do:

@pytest.mark.parametrize(
    "url",
    [
        "https://google.com",
        "https://amazon.com",
        "https://microsoft.com",
    ],
)
def test_domain(url, socket_enabled):
    requests.get(url)

The first URL is blocked and the others are allowed.
The error happens with @pytest.mark.enable_socket as well.

image

My setup.cfg:

[tool:pytest]
addopts = --allow-hosts=127.0.0.1

0.5.1: pytest is failing in `tests/test_async.py::test_httpx_fails` unit

I'm trying to package your module as an rpm package. So I'm using the typical PEP517 based build, install and test cycle used on building packages from non-root account.

  • python3 -sBm build -w --no-isolation
  • because I'm calling build with --no-isolation I'm using during all processes only locally installed modules
  • install .whl file in </install/prefix>
  • run pytest with PYTHONPATH pointing to sitearch and sitelib inside </install/prefix>

Allow host masks

I'm wondering if we could allow a range of IP as a mask. This is covered by the builtin [ipaddress](module.

consider this example

In [8]: from ipaddress import ip_network, ip_address

In [9]: ip_address('178.18.0.23') in ip_network('178.18.0.0/24')
Out[9]: True

In [10]: ip_address('178.18.0.1') in ip_network('178.18.0.0/24')
Out[10]: True

In [11]: ip_address('178.18.0.255') in ip_network('178.18.0.0/24')
Out[11]: True

In [12]: ip_address('178.18.1.1') in ip_network('178.18.0.0/24')
Out[12]: False

that check could complement this line

if host in allowed or (_is_unix_socket(inst.family) and allow_unix_socket):

I could send a PR if you are interested.

Issue with latest pytest-socket version while using testcontainers

Hi,
During update on of our service I noticed issue which was caused by latest version of pytest-socket . Issue occurs on bitbucket-pipelines , where I was testing it with python 3.10.6 and python 3.11.3

Here is code sample that is crushing:

from testcontainers.postgres import PostgresContainer

@pytest.fixture(scope="session")
def psql_container():
    postgres_container = PostgresContainer("postgres:14.1")
    with postgres_container as postgres:
        url = postgres.get_connection_url()

Here are logs that we are getting

address = ('localhost', 2375), timeout = 60, source_address = None
socket_options = [(6, 1, 1)]

    def create_connection(
        address,
        timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
        source_address=None,
        socket_options=None,
    ):
        """Connect to *address* and return the socket object.
    
        Convenience function.  Connect to *address* (a 2-tuple ``(host,
        port)``) and return the socket object.  Passing the optional
        *timeout* parameter will set the timeout on the socket instance
        before attempting to connect.  If no *timeout* is supplied, the
        global default timeout setting returned by :func:`socket.getdefaulttimeout`
        is used.  If *source_address* is set it must be a tuple of (host, port)
        for the socket to bind as a source address before making the connection.
        An host of '' or port 0 tells the OS to use the default.
        """
    
        host, port = address
        if host.startswith("["):
            host = host.strip("[]")
        err = None
    
        # Using the value from allowed_gai_family() in the context of getaddrinfo lets
        # us select whether to work with IPv4 DNS records, IPv6 records, or both.
        # The original create_connection function always returns all records.
        family = allowed_gai_family()
    
        try:
            host.encode("idna")
        except UnicodeError:
            return six.raise_from(
                LocationParseError(u"'%s', label empty or too long" % host), None
            )
    
        for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
            af, socktype, proto, canonname, sa = res
            sock = None
            try:
>               sock = socket.socket(af, socktype, proto)

/usr/local/lib/python3.10/site-packages/urllib3/util/connection.py:76: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

cls = <class 'pytest_socket.disable_socket.<locals>.GuardedSocket'>
family = <AddressFamily.AF_INET: 2>, type = <SocketKind.SOCK_STREAM: 1>
proto = 6, fileno = None

    def __new__(cls, family=-1, type=-1, proto=-1, fileno=None):
        if _is_unix_socket(family) and allow_unix_socket:
            return super().__new__(cls, family, type, proto, fileno)
    
>       raise SocketBlockedError()
E       pytest_socket.SocketBlockedError: A test tried to use socket.socket.

/usr/local/lib/python3.10/site-packages/pytest_socket.py:80: SocketBlockedError

During handling of the above exception, another exception occurred:

    @pytest.fixture(scope="session")
    def psql_container() -> Generator[Dict, None, None]:
        """Boot a PSQL container, yield psql_config and shut the container down after using"""
>       postgres_container = PostgresContainer("postgres:14.1")

tests/conftest.py:38: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/usr/local/lib/python3.10/site-packages/testcontainers/postgres.py:49: in __init__
    super(PostgresContainer, self).__init__(image=image, **kwargs)
/usr/local/lib/python3.10/site-packages/testcontainers/core/generic.py:27: in __init__
    super(DbContainer, self).__init__(image, **kwargs)
/usr/local/lib/python3.10/site-packages/testcontainers/core/container.py:19: in __init__
    self._docker = DockerClient(**(docker_client_kw or {}))
/usr/local/lib/python3.10/site-packages/testcontainers/core/docker_client.py:23: in __init__
    self.client = docker.from_env(**kwargs)
/usr/local/lib/python3.10/site-packages/docker/client.py:96: in from_env
    return cls(
/usr/local/lib/python3.10/site-packages/docker/client.py:45: in __init__
    self.api = APIClient(*args, **kwargs)
/usr/local/lib/python3.10/site-packages/docker/api/client.py:197: in __init__
    self._version = self._retrieve_server_version()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <docker.api.client.APIClient object at 0x7fa4d79f31f0>

    def _retrieve_server_version(self):
        try:
            return self.version(api_version=False)["ApiVersion"]
        except KeyError:
            raise DockerException(
                'Invalid response from docker daemon: key "ApiVersion"'
                ' is missing.'
            )
        except Exception as e:
>           raise DockerException(
                f'Error while fetching server API version: {e}'
            )
E           docker.errors.DockerException: Error while fetching server API version: A test tried to use socket.socket.

Here are libs version:

docker                        6.0.1
pytest                        7.3.1
pytest-socket                 0.6.0
testcontainers                3.7.1
urllib3                       1.26.15
requests                      2.28.2

Workaround solution is to downgrade lib to this version
pytest-socket==0.4.1

coverage reporting shows missing code, despite being run

Using pytest-cov to test a pytest plugin is a less-familiar pattern out there to follow.

The output of running the code with coverage reporting shows 67% coverage - awesome!

Adding the --cov-report=term-missing flag to pytest shows a large amount of code that is missing coverage, despite it actually being tested. Example:

---------- coverage: platform darwin, python 3.9.0-final-0 -----------
Name               Stmts   Miss  Cover   Missing
------------------------------------------------
pytest_socket.py      89     29    67%   2-12, 16-17, 25, 47-48, 65-66, 74-75, 83, 92-94, 104, 110, 116, 127, 131, 135-138, 143-146, 163
------------------------------------------------
TOTAL                 89     29    67%

pypy3 hangs on threading

For some reason, testing on pypy 6.0.0 (based on 3.5.3) has been hanging, causing build failures.

It might be due to the embedded server that we spin up during the test suite, as relates to a threading problem, possibly located in pypy3.5-6.0.0/lib-python/3/threading.py:293

For now, going to remove support for pypy - until such time there is a need/desire for it, and we can test effectively against it.

Feature request: Pass in custom exception

Hi,

First off, this looks like a super useful plugin. Clear use-case and implementation. I lack one feature, though, I have a function that has different outcomes based on an internet connection being available. Thus it runs different code based on a requests.exceptions.ConnectionError. I have now replicated your logic in my code but I was wondering whether you can see enabling passing down the exception class and message as a feature?

Issues with asyncio

Just stumbled upon this repo today, looks really interesting! I was testing it out on some py36 code which uses asyncio, and realised calling asyncio.get_event_loop() internally relies on socket.socket:

>>> asyncio.get_event_loop()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.6/asyncio/events.py", line 671, in get_event_loop
    return get_event_loop_policy().get_event_loop()
  File "/usr/lib/python3.6/asyncio/events.py", line 580, in get_event_loop
    self.set_event_loop(self.new_event_loop())
  File "/usr/lib/python3.6/asyncio/events.py", line 598, in new_event_loop
    return self._loop_factory()
  File "/usr/lib/python3.6/asyncio/unix_events.py", line 56, in __init__
    super().__init__(selector)
  File "/usr/lib/python3.6/asyncio/selector_events.py", line 67, in __init__
    self._make_self_pipe()
  File "/usr/lib/python3.6/asyncio/selector_events.py", line 129, in _make_self_pipe
    self._ssock, self._csock = self._socketpair()
  File "/usr/lib/python3.6/asyncio/unix_events.py", line 60, in _socketpair
    return socket.socketpair()
  File "/usr/lib/python3.6/socket.py", line 489, in socketpair
    a = socket(family, type, proto, a.detach())
...

in addition, I saw AttributeErrors like this when running on real code (likely related to the above?):

Traceback (most recent call last):
  File "/usr/lib/python3.6/asyncio/base_events.py", line 511, in __del__
    self.close()
  File "/usr/lib/python3.6/asyncio/unix_events.py", line 63, in close
    super().close()
  File "/usr/lib/python3.6/asyncio/selector_events.py", line 110, in close
    self._close_self_pipe()
  File "/usr/lib/python3.6/asyncio/selector_events.py", line 120, in _close_self_pipe
    self._remove_reader(self._ssock.fileno())
AttributeError: '_UnixSelectorEventLoop' object has no attribute '_ssock'

Given the intention of this plugin is to block all sockets, I can understand why this happens. But I'd like the ability to block external network requests yet still allow python to internally use things like asyncio. Any ideas if that's fixable here, or if it's worth persuing another solution?

@pytest.mark.enable_socket doesn't work

The mark to enable_socket doesn't seem to work. The fixture socket_enabled still works.

pytest-socket==0.3.1
pytest==3.10.0

Tried also on pytest==3.6.3 (earliest version supported according to pytest-socket metadata), same result.

MCVE test_something.py:

import socket
import pytest

def f():
    socket.socket()

@pytest.mark.enable_socket
def test_1():
    f()

def test_2(socket_enabled):
    f()

Demo:

$ pytest --disable-socket -v
======================================= test session starts =======================================
platform linux -- Python 3.7.0, pytest-3.10.0, py-1.7.0, pluggy-0.8.0 -- /tmp/example/.venv/bin/python3
cachedir: .pytest_cache
rootdir: /tmp/example, inifile:
plugins: socket-0.3.1
collected 2 items                                                                                 

test_something.py::test_1 FAILED                                                            [ 50%]
test_something.py::test_2 PASSED                                                            [100%]

============================================ FAILURES =============================================
_____________________________________________ test_1 ______________________________________________

    @pytest.mark.enable_socket
    def test_1():
>       f()

test_something.py:9: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
test_something.py:5: in f
    socket.socket()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

args = (), kwargs = {}

    def guarded(*args, **kwargs):
>       raise SocketBlockedError()
E       pytest_socket.SocketBlockedError: A test tried to use socket.socket.

.venv/lib/python3.7/site-packages/pytest_socket.py:72: SocketBlockedError
=============================== 1 failed, 1 passed in 0.04 seconds ================================```

Dependency Dashboard

This issue provides visibility into Renovate updates and their statuses. Learn more

This repository currently has no open or pending branches.


  • Check this box to trigger a request for Renovate to run again on this repository

socket_allow_hosts doesn't handle AF_UNIX sockets

socket_allow_hosts will always block AF_UNIX sockets, even if you pass --allow-unix-socket. The issue is that the code as currently written only handles AF_INET sockets, since host_from_connect_args assumes the args are always tuples, and will return None as the host otherwise.

A simple reproduction can be tested by creating a multiprocessing manager:

manager = multiprocessing.Manager()
lst = manager.list([1, 2, 3])

This will raise something like:

pytest_socket.SocketConnectBlockedError: A test tried to use socket.socket.connect() with host None (allowed: "foo").

socket_allow_hosts should allow any AF_UNIX socket connection if --allow-unix-socket is specified, and it should also work for AF_UNIX sockets with known socket (file) names if you pass the correct name in --allow-hosts.

Combination with --disable-socket option and enable_socket marker is not working

Environment Versions

  1. OS Type: MacOS 10.14.5
  2. Python version: Python 3.7.3
  3. Pytest version:
This is pytest version 5.2.2, imported from /v/lib/python3.7/site-packages/pytest.py
setuptools registered plugins:
  pytest-socket-0.3.3 at /v/lib/python3.7/site-packages/pytest_socket.py

Steps to replicate

  1. Copy the following code to t.py:
import pytest, socket

@pytest.mark.enable_socket
def test_explicitly_enable_socket():
    assert socket.socket(socket.AF_INET, socket.SOCK_STREAM
  1. Run pytest: pytest --disable-socket t.py

Expected result

The test passes:

============================= test session starts ==============================
platform darwin -- Python 3.7.3, pytest-5.2.2, py-1.8.0, pluggy-0.13.0
rootdir: /tmp
plugins: socket-0.3.3
collected 1 item                                                               

t.py .                                                                   [100%]

============================== 1 passed in 0.01s ===============================

Actual result

The test fails with a traceback:

============================= test session starts ==============================
platform darwin -- Python 3.7.3, pytest-5.2.2, py-1.8.0, pluggy-0.13.0
rootdir: /tmp
plugins: socket-0.3.3
collected 1 item                                                               

t.py F                                                                   [100%]

=================================== FAILURES ===================================
________________________ test_explicitly_enable_socket _________________________

    @pytest.mark.enable_socket
    def test_explicitly_enable_socket():
>       assert socket.socket(socket.AF_INET, socket.SOCK_STREAM)

t.py:5: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = (<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_STREAM: 1>), kwargs = {}

    def guarded(*args, **kwargs):
>       raise SocketBlockedError()
E       pytest_socket.SocketBlockedError: A test tried to use socket.socket.

/v/lib/python3.7/site-packages/pytest_socket.py:73: SocketBlockedError
============================== 1 failed in 0.04s ===============================

ability to specify different exception instead of custom `SocketBlockedError`

Some packages and their dependencies (such as tldextract using requests) are prepared to handle connection issues with standard exceptions.

Raising a custom one forces us to mock things that are not really important, if it'd be ok to let them fail.

Having the ability somehow to choose a different exception to be raised, such as standard/builtin ConnectionRefusedError would be nice.

I'm currently monkey patching pytest-socket in my conftest.py for this:

def pytest_runtest_setup():
    # monkey patch pytest_socket exception for a friendlier one
    # as some libs will react badly to RuntimeErrors
    import pytest_socket

    pytest_socket.SocketBlockedError = ConnectionRefusedError

0.5.0: pytest is failing in `tests/test_async.py::test_starlette` unit

I'm trying to package your module as an rpm package. So I'm using the typical PEP517 based build, install and test cycle used on building packages from non-root account.

  • python3 -sBm build -w --no-isolation
  • because I'm calling build with --no-isolation I'm using during all processes only locally installed modules
  • install .whl file in </install/prefix>
  • run pytest with PYTHONPATH pointing to sitearch and sitelib inside </install/prefix>

Here is pytest output:

+ PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-socket-0.5.0-2.fc35.x86_64/usr/lib64/python3.8/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-socket-0.5.0-2.fc35.x86_64/usr/lib/python3.8/site-packages
+ /usr/bin/pytest -ra
=========================================================================== test session starts ============================================================================
platform linux -- Python 3.8.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /home/tkloczko/rpmbuild/BUILD/pytest-socket-0.5.0
plugins: socket-0.5.0, cov-3.0.0, anyio-3.3.4, httpbin-1.0.1
collected 58 items

tests/test_async.py .F.                                                                                                                                              [  5%]
tests/test_combinations.py ..                                                                                                                                        [  8%]
tests/test_precedence.py ........                                                                                                                                    [ 22%]
tests/test_restrict_hosts.py .......................                                                                                                                 [ 62%]
tests/test_socket.py ......................                                                                                                                          [100%]

================================================================================= FAILURES =================================================================================
______________________________________________________________________________ test_starlette ______________________________________________________________________________

testdir = <Testdir local('/tmp/pytest-of-tkloczko/pytest-61/test_starlette0')>

    @unix_sockets_only
    def test_starlette(testdir):
        testdir.makepyfile(
            """
            from pytest_socket import disable_socket
            from starlette.responses import HTMLResponse
            from starlette.testclient import TestClient


            def pytest_runtest_setup():
                disable_socket()


            async def app(scope, receive, send):
                assert scope['type'] == 'http'
                response = HTMLResponse('<html><body>Hello, world!</body></html>')
                await response(scope, receive, send)


            def test_app():
                client = TestClient(app)
                response = client.get('/')
                assert response.status_code == 200
            """
        )
        result = testdir.runpytest("--disable-socket", "--allow-unix-socket")
>       result.assert_outcomes(passed=1, skipped=0, failed=0)
E       AssertionError: assert {'errors': 1,...pped': 0, ...} == {'errors': 0,...pped': 0, ...}
E         Omitting 4 identical items, use -vv to show
E         Differing items:
E         {'passed': 0} != {'passed': 1}
E         {'errors': 1} != {'errors': 0}
E         Use -v to get the full diff

/home/tkloczko/rpmbuild/BUILD/pytest-socket-0.5.0/tests/test_async.py:54: AssertionError
--------------------------------------------------------------------------- Captured stdout call ---------------------------------------------------------------------------
============================= test session starts ==============================
platform linux -- Python 3.8.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /tmp/pytest-of-tkloczko/pytest-61/test_starlette0
plugins: socket-0.5.0, cov-3.0.0, anyio-3.3.4, httpbin-1.0.1
collected 0 items / 1 error

==================================== ERRORS ====================================
______________________ ERROR collecting test_starlette.py ______________________
ImportError while importing test module '/tmp/pytest-of-tkloczko/pytest-61/test_starlette0/test_starlette.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib64/python3.8/importlib/__init__.py:127: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
test_starlette.py:2: in <module>
    from starlette.responses import HTMLResponse
E   ModuleNotFoundError: No module named 'starlette'
=========================== short test summary info ============================
ERROR test_starlette.py
!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
=============================== 1 error in 0.10s ===============================
========================================================================= short test summary info ==========================================================================
FAILED tests/test_async.py::test_starlette - AssertionError: assert {'errors': 1,...pped': 0, ...} == {'errors': 0,...pped': 0, ...}
====================================================================== 1 failed, 57 passed in 14.58s =======================================================================

poetry no longer creates "editable" metadata file, adds work during tests

poetry install --dev used to create the package local metadata, similar to python setup.py develop.
This usually created a pytest_socket.egg-info/ directory in the local path, but that's no longer the case.

Thus, during tests, running make test will always run the install target from the Makefile. It's not a long step, but we shouldn't run unnecessary commands if we don't have to.

dd-trace calls in separate thread do not fail test

DataDog/dd-trace-py#4179

Sometimes we get dd-trace errors in a thread when running pytest. I'm not sure what the cause is or if using a flag disabled this behavior, but what's disturbing to me is that I see the exception printed when running the tests and yet the tests do not fail. Shouldn't any socket call regardless of whether it occurs as part of the test itself or in some thread that gets started with the tests cause tests to fail? It does seem like the actual socket call is getting blocked, but the call should cause the tests to fail as well.

This is the pytest warning output:

test/<redacted>
  .../code/<redacted>/venv/lib/python3.10/site-packages/_pytest/threadexception.py:75: PytestUnhandledThreadExceptionWarning: Exception in thread ddtrace.internal.writer:AgentWriter
  
  Traceback (most recent call last):
    File ".../.pyenv/versions/3.10.6/lib/python3.10/threading.py", line 1016, in _bootstrap_inner
      self.run()
    File "...<redacted>/venv/lib/python3.10/site-packages/ddtrace/internal/periodic.py", line 70, in run
      self._target()
    File "...<redacted>/venv/lib/python3.10/site-packages/ddtrace/internal/writer.py", line 583, in periodic
      self.flush_queue(raise_exc=False)
    File "...<redacted>/venv/lib/python3.10/site-packages/ddtrace/internal/writer.py", line 559, in flush_queue
      self._retry_upload(self._send_payload, encoded, n_traces)
    File "...<redacted>/venv/lib/python3.10/site-packages/tenacity/__init__.py", line 406, in __call__
      do = self.iter(retry_state=retry_state)
    File "...<redacted>/venv/lib/python3.10/site-packages/tenacity/__init__.py", line 351, in iter
      return fut.result()
    File ".../.pyenv/versions/3.10.6/lib/python3.10/concurrent/futures/_base.py", line 451, in result
      return self.__get_result()
    File ".../.pyenv/versions/3.10.6/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
      raise self._exception
    File "...<redacted>/venv/lib/python3.10/site-packages/tenacity/__init__.py", line 409, in __call__
      result = fn(*args, **kwargs)
    File "...<redacted>/venv/lib/python3.10/site-packages/ddtrace/internal/writer.py", line 446, in _send_payload
      response = self._put(payload, headers)
    File "...<redacted>/venv/lib/python3.10/site-packages/ddtrace/internal/writer.py", line 398, in _put
      self._conn.request("PUT", self._endpoint, data, headers)
    File ".../.pyenv/versions/3.10.6/lib/python3.10/http/client.py", line 1282, in request
      self._send_request(method, url, body, headers, encode_chunked)
    File ".../.pyenv/versions/3.10.6/lib/python3.10/http/client.py", line 1328, in _send_request
      self.endheaders(body, encode_chunked=encode_chunked)
    File ".../.pyenv/versions/3.10.6/lib/python3.10/http/client.py", line 1277, in endheaders
      self._send_output(message_body, encode_chunked=encode_chunked)
    File ".../.pyenv/versions/3.10.6/lib/python3.10/http/client.py", line 1037, in _send_output
      self.send(msg)
    File ".../.pyenv/versions/3.10.6/lib/python3.10/http/client.py", line 975, in send
      self.connect()
    File ".../.pyenv/versions/3.10.6/lib/python3.10/http/client.py", line 941, in connect
      self.sock = self._create_connection(
    File ".../.pyenv/versions/3.10.6/lib/python3.10/socket.py", line 828, in create_connection
      sock = socket(af, socktype, proto)
    File "...<redacted>/venv/lib/python3.10/site-packages/pytest_socket.py", line 80, in __new__
      raise SocketBlockedError()
  pytest_socket.SocketBlockedError: A test tried to use socket.socket.
  
    warnings.warn(pytest.PytestUnhandledThreadExceptionWarning(msg))

Docker SDK unix socket connections blocked

I am using the Docker python SDK, and I get the following error when connections to 127.0.0.1 are allowed, and also passing --allow-unix-socket.

E docker.errors.DockerException: Error while fetching server API version: A test tried to > use socket.socket.connect() with host "None" (allowed: "127.0.0.1").

I'm using the default base_url for the docker client, which is the socket at unix:///var/run/docker/docker.sock, I believe.

Code reference:
https://github.com/docker/docker-py/blob/b27faa62e792c141a5d20c4acdd240fdac7d282f/docker/api/client.py#L79-L81

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.