Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ build
dist
*.pyc
.pytest_cache/
.ruff_cache/
# dump.rdb is created by redis-server, needed to run tests
dump.rdb
6 changes: 0 additions & 6 deletions .isort.cfg

This file was deleted.

2 changes: 1 addition & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
recursive-include docs *
recursive-include tests *
include pytest.ini AUTHORS.rst CODE_OF_CONDUCT.md pyproject.toml LICENSE README.rst tox.ini .coveragerc .isort.cfg .readthedocs.yaml
include pytest.ini AUTHORS.rst CODE_OF_CONDUCT.md pyproject.toml LICENSE README.rst tox.ini .coveragerc .readthedocs.yaml
prune docs/_build
global-exclude *.pyc
prune __pycache__
44 changes: 27 additions & 17 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
[tool.black]
line-length = 88
target-version = ['py37', 'py38', 'py39', 'py310', 'py311']
include = '\.pyi?$'
exclude = '''
/(
\.eggs
| \.git
| \.hg
| \.mypy_cache
| \.tox
| \.venv
| _build
| build
| dist
)/
'''
[tool.ruff]
extend-exclude = [
"__pycache__",
]

[tool.ruff.lint]
select = [
# pycodestyle
"E", "W",
# flake8
"F",
# isort
"I",
# pytest style
"PT",
# eradicate commented code
"ERA",
# ruff lint
"RUF",
]
ignore = [
# `format` will wrap lines.
"E501",
]

[tool.ruff.lint.isort]
known-first-party = ["dockerflow"]
3 changes: 2 additions & 1 deletion src/dockerflow/django/middleware.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging
import re
import time
import typing
import urllib
import uuid

Expand All @@ -16,7 +17,7 @@ class DockerflowMiddleware(MiddlewareMixin):
https://github.com/mozilla-services/Dockerflow/blob/main/docs/mozlog.md
"""

viewpatterns = [
viewpatterns: typing.ClassVar = [
(re.compile(r"/__version__/?$"), views.version),
(re.compile(r"/__heartbeat__/?$"), views.heartbeat),
(re.compile(r"/__lbheartbeat__/?$"), views.lbheartbeat),
Expand Down
5 changes: 3 additions & 2 deletions src/dockerflow/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import socket
import sys
import traceback
import typing


class SafeJSONEncoder(json.JSONEncoder):
Expand All @@ -32,7 +33,7 @@ class JsonLogFormatter(logging.Formatter):
LOGGING_FORMAT_VERSION = "2.0"

# Map from Python logging to Syslog severity levels
SYSLOG_LEVEL_MAP = {
SYSLOG_LEVEL_MAP: typing.ClassVar = {
50: 2, # CRITICAL
40: 3, # ERROR
30: 4, # WARNING
Expand All @@ -43,7 +44,7 @@ class JsonLogFormatter(logging.Formatter):
# Syslog level to use when/if python level isn't found in map
DEFAULT_SYSLOG_LEVEL = 7

EXCLUDED_LOGRECORD_ATTRS = set(
EXCLUDED_LOGRECORD_ATTRS: typing.ClassVar = set(
(
"args",
"asctime",
Expand Down
4 changes: 2 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import dockerflow.checks.registry


@pytest.fixture
@pytest.fixture()
def version_content():
"""
as documented on https://github.com/mozilla-services/Dockerflow/blob/main/docs/version_object.md
Expand All @@ -20,6 +20,6 @@ def version_content():


@pytest.fixture(autouse=True)
def clear_checks():
def _clear_checks():
yield
dockerflow.checks.registry.clear_checks()
9 changes: 4 additions & 5 deletions tests/core/test_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@


@pytest.fixture()
def reset_logging():
def _reset_logging():
logging.shutdown()
reload(logging)

Expand All @@ -31,7 +31,8 @@ def assert_records(records):
return details


def test_initialization_from_ini(reset_logging, caplog, tmpdir):
@pytest.mark.usefixtures("_reset_logging")
def test_initialization_from_ini(caplog, tmpdir):
ini_content = textwrap.dedent(
"""
[loggers]
Expand Down Expand Up @@ -229,7 +230,5 @@ def test_ignore_json_message(caplog):
}
}
}
""".replace(
"\\", "\\\\"
)
""".replace("\\", "\\\\")
) # HACK: Fix escaping for easy copy/paste
31 changes: 16 additions & 15 deletions tests/django/test_django.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,19 @@


@pytest.fixture(autouse=True)
def reset_checks():
def _reset_checks():
yield
registry.registered_checks = set()
registry.deployment_checks = set()


@pytest.fixture(autouse=True)
def setup_request_summary_logger(dockerflow_middleware):
def _setup_request_summary_logger(dockerflow_middleware):
dockerflow_middleware.summary_logger.addHandler(logging.NullHandler())
dockerflow_middleware.summary_logger.setLevel(logging.INFO)


@pytest.fixture
@pytest.fixture()
def dockerflow_middleware():
return DockerflowMiddleware(get_response=HttpResponse())

Expand All @@ -55,7 +55,7 @@ def test_version_missing(dockerflow_middleware, mocker, rf):
assert response.status_code == 404


@pytest.mark.django_db
@pytest.mark.django_db()
def test_heartbeat(client, settings):
response = client.get("/__heartbeat__")
assert response.status_code == 200
Expand All @@ -73,7 +73,7 @@ def test_heartbeat(client, settings):
assert content.get("details") is None


@pytest.mark.django_db
@pytest.mark.django_db()
def test_heartbeat_debug(client, settings):
settings.DOCKERFLOW_CHECKS = [
"tests.django.django_checks.warning",
Expand All @@ -89,7 +89,7 @@ def test_heartbeat_debug(client, settings):
assert content["details"]


@pytest.mark.django_db
@pytest.mark.django_db()
def test_heartbeat_silenced(client, settings):
settings.DOCKERFLOW_CHECKS = [
"tests.django.django_checks.warning",
Expand All @@ -107,8 +107,9 @@ def test_heartbeat_silenced(client, settings):
assert "error" not in content["details"]


@pytest.mark.django_db
def test_heartbeat_logging(dockerflow_middleware, reset_checks, rf, settings, caplog):
@pytest.mark.django_db()
@pytest.mark.usefixtures("_reset_checks")
def test_heartbeat_logging(dockerflow_middleware, rf, settings, caplog):
request = rf.get("/__heartbeat__")
settings.DOCKERFLOW_CHECKS = [
"tests.django.django_checks.warning",
Expand All @@ -123,7 +124,7 @@ def test_heartbeat_logging(dockerflow_middleware, reset_checks, rf, settings, ca
assert ("WARNING", "tests.checks.W001: some warning") in logged


@pytest.mark.django_db
@pytest.mark.django_db()
def test_lbheartbeat_makes_no_db_queries(dockerflow_middleware, rf):
queries = CaptureQueriesContext(connection)
request = rf.get("/__lbheartbeat__")
Expand All @@ -133,7 +134,7 @@ def test_lbheartbeat_makes_no_db_queries(dockerflow_middleware, rf):
assert len(queries) == 0


@pytest.mark.django_db
@pytest.mark.django_db()
def test_redis_check(client, settings):
settings.DOCKERFLOW_CHECKS = ["dockerflow.django.checks.check_redis_connected"]
checks.register()
Expand All @@ -152,7 +153,7 @@ def assert_log_record(request, record, errno=0, level=logging.INFO):
assert isinstance(record.t, int)


@pytest.fixture
@pytest.fixture()
def dockerflow_request(rf):
return rf.get("/", HTTP_USER_AGENT="dockerflow/tests", HTTP_ACCEPT_LANGUAGE="tlh")

Expand Down Expand Up @@ -248,15 +249,15 @@ def test_check_database_connected_misconfigured(mocker):
assert errors[0].id == health.ERROR_MISCONFIGURED_DATABASE


@pytest.mark.django_db
@pytest.mark.django_db()
def test_check_database_connected_unsuable(mocker):
mocker.patch("django.db.connection.is_usable", return_value=False)
errors = checks.check_database_connected([])
assert len(errors) == 1
assert errors[0].id == health.ERROR_UNUSABLE_DATABASE


@pytest.mark.django_db
@pytest.mark.django_db()
def test_check_database_connected_success(mocker):
errors = checks.check_database_connected([])
assert errors == []
Expand All @@ -272,7 +273,7 @@ def test_check_migrations_applied_cannot_check_migrations(exception, mocker):
assert errors[0].id == health.INFO_CANT_CHECK_MIGRATIONS


@pytest.mark.django_db
@pytest.mark.django_db()
def test_check_migrations_applied_unapplied_migrations(mocker):
mock_loader = mocker.patch("django.db.migrations.loader.MigrationLoader")
mock_loader.return_value.applied_migrations = ["spam", "eggs"]
Expand Down Expand Up @@ -306,7 +307,7 @@ def test_check_migrations_applied_unapplied_migrations(mocker):


@pytest.mark.parametrize(
"exception,error",
("exception", "error"),
[
(redis.ConnectionError, health.ERROR_CANNOT_CONNECT_REDIS),
(NotImplementedError, health.ERROR_MISSING_REDIS_CLIENT),
Expand Down
6 changes: 3 additions & 3 deletions tests/fastapi/test_fastapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ def create_app():
return app


@pytest.fixture
@pytest.fixture()
def app():
return create_app()


@pytest.fixture
@pytest.fixture()
def client(app):
return TestClient(app)

Expand Down Expand Up @@ -69,7 +69,7 @@ def test_mozlog_failure(client, mocker, caplog):
"dockerflow.fastapi.views.get_version", side_effect=ValueError("crash")
)

with pytest.raises(ValueError):
with pytest.raises(expected_exception=ValueError):
client.get("/__version__")

record = caplog.records[0]
Expand Down
4 changes: 2 additions & 2 deletions tests/flask/migrations/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from logging.config import fileConfig

from alembic import context # no:qa
from flask import current_app # noqa
from flask import current_app
from sqlalchemy import engine_from_config, pool

# this is the Alembic Config object, which provides
Expand All @@ -24,7 +24,7 @@

# other values from the config, defined by the needs of env.py,
# can be acquired:
# my_important_option = config.get_main_option("my_important_option")
# my_important_option = config.get_main_option("my_important_option") # noqa
# ... etc.


Expand Down
Loading