Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move thread activation to start method #1032

Merged
merged 1 commit into from
Oct 25, 2023
Merged

Conversation

samamorgan
Copy link
Contributor

@samamorgan samamorgan commented Oct 6, 2022

This moves activation of LiveServer.thread to a method. My primary motivation here is to delay thread activation so I can change the parameters of the thread in an overriden live_server fixture. This provides a work-around to issue #294 using the following override:

import os

import pytest
from django.test.testcases import _StaticFilesHandler
from pytest_django import live_server_helper
from pytest_django.lazy_django import skip_if_no_django


@pytest.fixture(scope="session")
def live_server(request):
    skip_if_no_django()

    addr = (
        request.config.getvalue("liveserver")
        or os.getenv("DJANGO_LIVE_TEST_SERVER_ADDRESS")
        or "localhost"
    )

    server = live_server_helper.LiveServer(addr)
    server.thread.static_handler = _StaticFilesHandler  # Force _StaticFilesHandler
    server.start()
    request.addfinalizer(server.stop)

    return server

@samamorgan
Copy link
Contributor Author

Note: The failing tests here aren't failing, it's just an issue with the codecov upload.

Copy link
Member

@bluetech bluetech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not opposed to this, but needs a couple of changes:

  1. To keep backward compat (not that it's a public interface, but who knows), let's add a *, start: bool = True argument to __init__, and add a call to self.start if start is true. You will then need to pass start=False.
  2. The inc_thread_sharing part needs to be done in start, not in __init__, to match the stop.

@samamorgan
Copy link
Contributor Author

I'm not opposed to this, but needs a couple of changes:

  1. To keep backward compat (not that it's a public interface, but who knows), let's add a *, start: bool = True argument to __init__, and add a call to self.start if start is true. You will then need to pass start=False.
  2. The inc_thread_sharing part needs to be done in start, not in __init__, to match the stop.

Thanks for the quick feedback! I did both of these, then went a little ham and took it a step beyond.

This code was a little smelly. Imports inside the constructor, messing around with threads, etc. I refactored it to move all imports to the top, and it's now subclassing LiveServerThread rather than implementing a thread internally. This is functionally the same, but cleans up a lot of unnecessary calls to self.thread/live_server.thread. The class behaves like a thread, so why not just make it one?

If I went too hard here, I'm happy to back off and just implement the requested changes.

@samamorgan
Copy link
Contributor Author

Alright, tests failing now. Looks like I'm misunderstanding something about these imports. Is there an explanation I missed somewhere about why imports are happening in a function instead of the top of the module?

@bluetech
Copy link
Member

importing django has some side-effects, sometimes it requires DJANGO_SETTINGS_MODULE and such to be defined, etc. So it must always be imported lazily in pytest-django.

@samamorgan
Copy link
Contributor Author

Backed off on the subclassing decision. I spent way too much time trying to implement a lazy import mechanism just to have it fall on its face.

I very much dislike the imports inside methods. Makes my heart hurt. I don't know enough about this library to really understand what a good alternative would be though, so the code smells get to stay!

@samamorgan
Copy link
Contributor Author

@bluetech Anything blocking this one?

@@ -538,6 +538,7 @@ def live_server(request):

server = live_server_helper.LiveServer(addr)
request.addfinalizer(server.stop)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

port = int(port_str)
except ValueError:
host = addr
port = 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the entire liveserver_kwargs business was to avoid this line, i.e. not duplicate Django's default in case it changes.

@bluetech
Copy link
Member

Thanks @samamorgan. I rebased and removed unrelated changes from the diff. Merging now.

@bluetech bluetech merged commit a4ea66d into pytest-dev:master Oct 25, 2023
14 of 15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants