chore: automatic commit 2025-04-30 12:48
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
#!/usr/bin/env python
|
||||
from ._version import version as __version__
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
35
venv/lib/python3.11/site-packages/pytest_flask/_internal.py
Normal file
35
venv/lib/python3.11/site-packages/pytest_flask/_internal.py
Normal file
@@ -0,0 +1,35 @@
|
||||
import functools
|
||||
import warnings
|
||||
|
||||
|
||||
def deprecated(reason):
|
||||
"""Decorator which can be used to mark function or method as deprecated.
|
||||
It will result a warning being emmitted when the function is called."""
|
||||
|
||||
def decorator(func):
|
||||
@functools.wraps(func)
|
||||
def deprecated_call(*args, **kwargs):
|
||||
warnings.simplefilter("always", DeprecationWarning)
|
||||
warnings.warn(reason, DeprecationWarning, stacklevel=2)
|
||||
warnings.simplefilter("default", DeprecationWarning)
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return deprecated_call
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
def _rewrite_server_name(server_name, new_port):
|
||||
"""Rewrite server port in ``server_name`` with ``new_port`` value."""
|
||||
sep = ":"
|
||||
if sep in server_name:
|
||||
server_name, _ = server_name.split(sep, 1)
|
||||
return sep.join((server_name, new_port))
|
||||
|
||||
|
||||
def _determine_scope(*, fixture_name, config):
|
||||
return config.getini("live_server_scope")
|
||||
|
||||
|
||||
def _make_accept_header(mimetype):
|
||||
return [("Accept", mimetype)]
|
||||
@@ -0,0 +1,5 @@
|
||||
# coding: utf-8
|
||||
# file generated by setuptools_scm
|
||||
# don't change, don't track in version control
|
||||
version = '1.2.0'
|
||||
version_tuple = (1, 2, 0)
|
||||
135
venv/lib/python3.11/site-packages/pytest_flask/fixtures.py
Normal file
135
venv/lib/python3.11/site-packages/pytest_flask/fixtures.py
Normal file
@@ -0,0 +1,135 @@
|
||||
#!/usr/bin/env python
|
||||
import socket
|
||||
import warnings
|
||||
|
||||
import pytest
|
||||
from flask import _request_ctx_stack
|
||||
|
||||
from ._internal import _determine_scope
|
||||
from ._internal import _make_accept_header
|
||||
from ._internal import _rewrite_server_name
|
||||
from ._internal import deprecated
|
||||
from .live_server import LiveServer
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def client(app):
|
||||
"""A Flask test client. An instance of :class:`flask.testing.TestClient`
|
||||
by default.
|
||||
"""
|
||||
with app.test_client() as client:
|
||||
yield client
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def client_class(request, client):
|
||||
"""Uses to set a ``client`` class attribute to current Flask test client::
|
||||
|
||||
@pytest.mark.usefixtures('client_class')
|
||||
class TestView:
|
||||
|
||||
def login(self, email, password):
|
||||
credentials = {'email': email, 'password': password}
|
||||
return self.client.post(url_for('login'), data=credentials)
|
||||
|
||||
def test_login(self):
|
||||
assert self.login('foo@example.com', 'pass').status_code == 200
|
||||
|
||||
"""
|
||||
if request.cls is not None:
|
||||
request.cls.client = client
|
||||
|
||||
|
||||
@pytest.fixture(scope=_determine_scope)
|
||||
def live_server(request, app, pytestconfig):
|
||||
"""Run application in a separate process.
|
||||
|
||||
When the ``live_server`` fixture is applied, the ``url_for`` function
|
||||
works as expected::
|
||||
|
||||
def test_server_is_up_and_running(live_server):
|
||||
index_url = url_for('index', _external=True)
|
||||
assert index_url == 'http://localhost:5000/'
|
||||
|
||||
res = urllib2.urlopen(index_url)
|
||||
assert res.code == 200
|
||||
|
||||
"""
|
||||
# Set or get a port
|
||||
port = app.config.get("LIVESERVER_PORT", None)
|
||||
if not port:
|
||||
port = pytestconfig.getvalue("live_server_port")
|
||||
|
||||
if port == 0:
|
||||
# Bind to an open port
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.bind(("", 0))
|
||||
port = s.getsockname()[1]
|
||||
s.close()
|
||||
|
||||
host = pytestconfig.getvalue("live_server_host")
|
||||
|
||||
# Explicitly set application ``SERVER_NAME`` for test suite
|
||||
original_server_name = app.config["SERVER_NAME"] or "localhost"
|
||||
final_server_name = _rewrite_server_name(original_server_name, str(port))
|
||||
app.config["SERVER_NAME"] = final_server_name
|
||||
|
||||
wait = request.config.getvalue("live_server_wait")
|
||||
clean_stop = request.config.getvalue("live_server_clean_stop")
|
||||
server = LiveServer(app, host, port, wait, clean_stop)
|
||||
if request.config.getvalue("start_live_server"):
|
||||
server.start()
|
||||
|
||||
request.addfinalizer(server.stop)
|
||||
yield server
|
||||
|
||||
if original_server_name is not None:
|
||||
app.config["SERVER_NAME"] = original_server_name
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def config(app):
|
||||
"""An application config."""
|
||||
return app.config
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def request_ctx(app):
|
||||
"""The request context which contains all request relevant information,
|
||||
e.g. `session`, `g`, `flashes`, etc.
|
||||
"""
|
||||
warnings.warn(
|
||||
"In Werzeug 2.0.0, the Client request methods "
|
||||
"(client.get, client.post) always return an instance of TestResponse. This "
|
||||
"class provides a reference to the request object through 'response.request' "
|
||||
"The fixture 'request_ctx' is deprecated and will be removed in the future, using TestResponse.request "
|
||||
"is the prefered way.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return _request_ctx_stack.top
|
||||
|
||||
|
||||
@pytest.fixture(params=["application/json", "text/html"])
|
||||
def mimetype(request):
|
||||
return request.param
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def accept_mimetype(mimetype):
|
||||
return _make_accept_header(mimetype)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def accept_json(request):
|
||||
return _make_accept_header("application/json")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def accept_jsonp():
|
||||
return _make_accept_header("application/json-p")
|
||||
|
||||
|
||||
@pytest.fixture(params=["*", "*/*"])
|
||||
def accept_any(request):
|
||||
return _make_accept_header(request.param)
|
||||
@@ -0,0 +1,92 @@
|
||||
import logging
|
||||
import multiprocessing
|
||||
import os
|
||||
import signal
|
||||
import socket
|
||||
import time
|
||||
|
||||
import pytest
|
||||
|
||||
from ._internal import deprecated
|
||||
|
||||
|
||||
class LiveServer:
|
||||
"""The helper class used to manage a live server. Handles creation and
|
||||
stopping application in a separate process.
|
||||
|
||||
:param app: The application to run.
|
||||
:param host: The host where to listen (default localhost).
|
||||
:param port: The port to run application.
|
||||
:param wait: The timeout after which test case is aborted if
|
||||
application is not started.
|
||||
"""
|
||||
|
||||
def __init__(self, app, host, port, wait, clean_stop=False):
|
||||
self.app = app
|
||||
self.port = port
|
||||
self.host = host
|
||||
self.wait = wait
|
||||
self.clean_stop = clean_stop
|
||||
self._process = None
|
||||
|
||||
def start(self):
|
||||
"""Start application in a separate process."""
|
||||
|
||||
def worker(app, host, port):
|
||||
app.run(host=host, port=port, use_reloader=False, threaded=True)
|
||||
|
||||
self._process = multiprocessing.Process(
|
||||
target=worker, args=(self.app, self.host, self.port)
|
||||
)
|
||||
self._process.daemon = True
|
||||
self._process.start()
|
||||
|
||||
keep_trying = True
|
||||
start_time = time.time()
|
||||
while keep_trying:
|
||||
elapsed_time = time.time() - start_time
|
||||
if elapsed_time > self.wait:
|
||||
pytest.fail(
|
||||
"Failed to start the server after {!s} "
|
||||
"seconds.".format(self.wait)
|
||||
)
|
||||
if self._is_ready():
|
||||
keep_trying = False
|
||||
|
||||
def _is_ready(self):
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
try:
|
||||
sock.connect((self.host, self.port))
|
||||
except socket.error:
|
||||
ret = False
|
||||
else:
|
||||
ret = True
|
||||
finally:
|
||||
sock.close()
|
||||
return ret
|
||||
|
||||
def stop(self):
|
||||
"""Stop application process."""
|
||||
if self._process:
|
||||
if self.clean_stop and self._stop_cleanly():
|
||||
return
|
||||
if self._process.is_alive():
|
||||
# If it's still alive, kill it
|
||||
self._process.terminate()
|
||||
|
||||
def _stop_cleanly(self, timeout=5):
|
||||
"""Attempts to stop the server cleanly by sending a SIGINT signal and waiting for
|
||||
``timeout`` seconds.
|
||||
|
||||
:return: True if the server was cleanly stopped, False otherwise.
|
||||
"""
|
||||
try:
|
||||
os.kill(self._process.pid, signal.SIGINT)
|
||||
self._process.join(timeout)
|
||||
return True
|
||||
except Exception as ex:
|
||||
logging.error("Failed to join the live server process: %r", ex)
|
||||
return False
|
||||
|
||||
def __repr__(self):
|
||||
return "<LiveServer listening at %s>" % self.url()
|
||||
198
venv/lib/python3.11/site-packages/pytest_flask/plugin.py
Normal file
198
venv/lib/python3.11/site-packages/pytest_flask/plugin.py
Normal file
@@ -0,0 +1,198 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
A py.test plugin which helps testing Flask applications.
|
||||
|
||||
:copyright: (c) by Vital Kudzelka
|
||||
:license: MIT
|
||||
"""
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
from flask import json
|
||||
from werkzeug.utils import cached_property
|
||||
|
||||
from .fixtures import accept_any
|
||||
from .fixtures import accept_json
|
||||
from .fixtures import accept_jsonp
|
||||
from .fixtures import accept_mimetype
|
||||
from .fixtures import client
|
||||
from .fixtures import client_class
|
||||
from .fixtures import config
|
||||
from .fixtures import live_server
|
||||
from .fixtures import request_ctx
|
||||
from .pytest_compat import getfixturevalue
|
||||
|
||||
|
||||
class JSONResponse:
|
||||
"""Mixin with testing helper methods for JSON responses."""
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, int):
|
||||
return self.status_code == other
|
||||
return super().__eq__(other)
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
|
||||
def pytest_assertrepr_compare(op, left, right):
|
||||
if isinstance(left, JSONResponse) and op == "==" and isinstance(right, int):
|
||||
return [
|
||||
"Mismatch in status code for response: {} != {}".format(
|
||||
left.status_code,
|
||||
right,
|
||||
),
|
||||
"Response status: {}".format(left.status),
|
||||
]
|
||||
return None
|
||||
|
||||
|
||||
def _make_test_response_class(response_class):
|
||||
"""Extends the response class with special attribute to test JSON
|
||||
responses. Don't override user-defined `json` attribute if any.
|
||||
|
||||
:param response_class: An original response class.
|
||||
"""
|
||||
if "json" in response_class.__dict__:
|
||||
return response_class
|
||||
|
||||
return type(str(JSONResponse), (response_class, JSONResponse), {})
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _monkeypatch_response_class(request, monkeypatch):
|
||||
"""Set custom response class before test suite and restore the original
|
||||
after. Custom response has `json` property to easily test JSON responses::
|
||||
|
||||
@app.route('/ping')
|
||||
def ping():
|
||||
return jsonify(ping='pong')
|
||||
|
||||
def test_json(client):
|
||||
res = client.get(url_for('ping'))
|
||||
assert res.json == {'ping': 'pong'}
|
||||
|
||||
"""
|
||||
|
||||
if "app" not in request.fixturenames:
|
||||
return
|
||||
|
||||
app = getfixturevalue(request, "app")
|
||||
monkeypatch.setattr(
|
||||
app, "response_class", _make_test_response_class(app.response_class)
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _push_request_context(request):
|
||||
"""During tests execution request context has been pushed, e.g. `url_for`,
|
||||
`session`, etc. can be used in tests as is::
|
||||
|
||||
def test_app(app, client):
|
||||
assert client.get(url_for('myview')).status_code == 200
|
||||
|
||||
"""
|
||||
if "app" not in request.fixturenames:
|
||||
return
|
||||
|
||||
app = getfixturevalue(request, "app")
|
||||
|
||||
# Get application bound to the live server if ``live_server`` fixture
|
||||
# is applied. Live server application has an explicit ``SERVER_NAME``,
|
||||
# so ``url_for`` function generates a complete URL for endpoint which
|
||||
# includes application port as well.
|
||||
if "live_server" in request.fixturenames:
|
||||
app = getfixturevalue(request, "live_server").app
|
||||
|
||||
ctx = app.test_request_context()
|
||||
ctx.push()
|
||||
|
||||
def teardown():
|
||||
ctx.pop()
|
||||
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _configure_application(request, monkeypatch):
|
||||
"""Use `pytest.mark.options` decorator to pass options to your application
|
||||
factory::
|
||||
|
||||
@pytest.mark.options(debug=False)
|
||||
def test_something(app):
|
||||
assert not app.debug, 'the application works not in debug mode!'
|
||||
|
||||
"""
|
||||
if "app" not in request.fixturenames:
|
||||
return
|
||||
|
||||
app = getfixturevalue(request, "app")
|
||||
for options in request.node.iter_markers("options"):
|
||||
for key, value in options.kwargs.items():
|
||||
monkeypatch.setitem(app.config, key.upper(), value)
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
group = parser.getgroup("flask")
|
||||
group.addoption(
|
||||
"--start-live-server",
|
||||
action="store_true",
|
||||
dest="start_live_server",
|
||||
default=True,
|
||||
help="start server automatically when live_server "
|
||||
"fixture is applied (enabled by default).",
|
||||
)
|
||||
group.addoption(
|
||||
"--no-start-live-server",
|
||||
action="store_false",
|
||||
dest="start_live_server",
|
||||
help="don't start server automatically when live_server " "fixture is applied.",
|
||||
)
|
||||
group.addoption(
|
||||
"--live-server-wait",
|
||||
action="store",
|
||||
dest="live_server_wait",
|
||||
default=5,
|
||||
type=float,
|
||||
help="the timeout after which test case is aborted if live server is "
|
||||
" not started.",
|
||||
)
|
||||
group.addoption(
|
||||
"--live-server-clean-stop",
|
||||
action="store_true",
|
||||
dest="live_server_clean_stop",
|
||||
default=True,
|
||||
help="attempt to kill the live server cleanly.",
|
||||
)
|
||||
group.addoption(
|
||||
"--no-live-server-clean-stop",
|
||||
action="store_false",
|
||||
dest="live_server_clean_stop",
|
||||
help="terminate the server forcefully after stop.",
|
||||
)
|
||||
group.addoption(
|
||||
"--live-server-host",
|
||||
action="store",
|
||||
default="localhost",
|
||||
type=str,
|
||||
help="use a host where to listen (default localhost).",
|
||||
)
|
||||
group.addoption(
|
||||
"--live-server-port",
|
||||
action="store",
|
||||
default=0,
|
||||
type=int,
|
||||
help="use a fixed port for the live_server fixture.",
|
||||
)
|
||||
parser.addini(
|
||||
"live_server_scope",
|
||||
"modify the scope of the live_server fixture.",
|
||||
default="session",
|
||||
)
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
config.addinivalue_line(
|
||||
"markers", "app(options): pass options to your application factory"
|
||||
)
|
||||
config.addinivalue_line("markers", "options: app config manipulation")
|
||||
@@ -0,0 +1,5 @@
|
||||
def getfixturevalue(request, value):
|
||||
if hasattr(request, "getfixturevalue"):
|
||||
return request.getfixturevalue(value)
|
||||
|
||||
return request.getfuncargvalue(value) # pragma: no cover
|
||||
Reference in New Issue
Block a user