mirror of
https://github.com/osm-search/Nominatim.git
synced 2026-02-16 15:47:58 +00:00
add debug output for unit tests
This uses the debug output facility meant for pretty HTML output to give us debugging output for the unit tests.
This commit is contained in:
@@ -7,8 +7,9 @@
|
|||||||
"""
|
"""
|
||||||
Functions for specialised logging with HTML output.
|
Functions for specialised logging with HTML output.
|
||||||
"""
|
"""
|
||||||
from typing import Any, Optional, cast
|
from typing import Any, cast
|
||||||
from contextvars import ContextVar
|
from contextvars import ContextVar
|
||||||
|
import textwrap
|
||||||
import io
|
import io
|
||||||
|
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
@@ -30,6 +31,8 @@ class BaseLogger:
|
|||||||
in derived classes which implement logging functionality.
|
in derived classes which implement logging functionality.
|
||||||
"""
|
"""
|
||||||
def get_buffer(self) -> str:
|
def get_buffer(self) -> str:
|
||||||
|
""" Return the current content of the log buffer.
|
||||||
|
"""
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
def function(self, func: str, **kwargs: Any) -> None:
|
def function(self, func: str, **kwargs: Any) -> None:
|
||||||
@@ -61,16 +64,15 @@ class BaseLogger:
|
|||||||
class HTMLLogger(BaseLogger):
|
class HTMLLogger(BaseLogger):
|
||||||
""" Logger that formats messages in HTML.
|
""" Logger that formats messages in HTML.
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self) -> None:
|
||||||
self.buffer = io.StringIO()
|
self.buffer = io.StringIO()
|
||||||
|
|
||||||
|
|
||||||
def get_buffer(self) -> str:
|
def get_buffer(self) -> str:
|
||||||
return HTML_HEADER + self.buffer.getvalue() + HTML_FOOTER
|
return HTML_HEADER + self.buffer.getvalue() + HTML_FOOTER
|
||||||
|
|
||||||
|
|
||||||
def function(self, func: str, **kwargs: Any) -> None:
|
def function(self, func: str, **kwargs: Any) -> None:
|
||||||
""" Start a new debug chapter for the given function and its parameters.
|
|
||||||
"""
|
|
||||||
self._write(f"<h1>Debug output for {func}()</h1>\n<p>Parameters:<dl>")
|
self._write(f"<h1>Debug output for {func}()</h1>\n<p>Parameters:<dl>")
|
||||||
for name, value in kwargs.items():
|
for name, value in kwargs.items():
|
||||||
self._write(f'<dt>{name}</dt><dd>{self._python_var(value)}</dd>')
|
self._write(f'<dt>{name}</dt><dd>{self._python_var(value)}</dd>')
|
||||||
@@ -78,25 +80,18 @@ class HTMLLogger(BaseLogger):
|
|||||||
|
|
||||||
|
|
||||||
def section(self, heading: str) -> None:
|
def section(self, heading: str) -> None:
|
||||||
""" Start a new section with the given title.
|
|
||||||
"""
|
|
||||||
self._write(f"<h2>{heading}</h2>")
|
self._write(f"<h2>{heading}</h2>")
|
||||||
|
|
||||||
|
|
||||||
def comment(self, text: str) -> None:
|
def comment(self, text: str) -> None:
|
||||||
""" Add a simple comment to the debug output.
|
|
||||||
"""
|
|
||||||
self._write(f"<p>{text}</p>")
|
self._write(f"<p>{text}</p>")
|
||||||
|
|
||||||
|
|
||||||
def var_dump(self, heading: str, var: Any) -> None:
|
def var_dump(self, heading: str, var: Any) -> None:
|
||||||
""" Print the content of the variable to the debug output prefixed by
|
|
||||||
the given heading.
|
|
||||||
"""
|
|
||||||
self._write(f'<h5>{heading}</h5>{self._python_var(var)}')
|
self._write(f'<h5>{heading}</h5>{self._python_var(var)}')
|
||||||
|
|
||||||
|
|
||||||
def sql(self, conn: AsyncConnection, statement: 'sa.Executable') -> None:
|
def sql(self, conn: AsyncConnection, statement: 'sa.Executable') -> None:
|
||||||
""" Dump the SQL statement to debug output.
|
|
||||||
"""
|
|
||||||
sqlstr = str(cast('sa.ClauseElement', statement)
|
sqlstr = str(cast('sa.ClauseElement', statement)
|
||||||
.compile(conn.sync_engine, compile_kwargs={"literal_binds": True}))
|
.compile(conn.sync_engine, compile_kwargs={"literal_binds": True}))
|
||||||
if CODE_HIGHLIGHT:
|
if CODE_HIGHLIGHT:
|
||||||
@@ -121,6 +116,51 @@ class HTMLLogger(BaseLogger):
|
|||||||
self.buffer.write(text)
|
self.buffer.write(text)
|
||||||
|
|
||||||
|
|
||||||
|
class TextLogger(BaseLogger):
|
||||||
|
""" Logger creating output suitable for the console.
|
||||||
|
"""
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.buffer = io.StringIO()
|
||||||
|
|
||||||
|
|
||||||
|
def get_buffer(self) -> str:
|
||||||
|
return self.buffer.getvalue()
|
||||||
|
|
||||||
|
|
||||||
|
def function(self, func: str, **kwargs: Any) -> None:
|
||||||
|
self._write(f"#### Debug output for {func}()\n\nParameters:\n")
|
||||||
|
for name, value in kwargs.items():
|
||||||
|
self._write(f' {name}: {self._python_var(value)}\n')
|
||||||
|
self._write('\n')
|
||||||
|
|
||||||
|
|
||||||
|
def section(self, heading: str) -> None:
|
||||||
|
self._write(f"\n# {heading}\n\n")
|
||||||
|
|
||||||
|
|
||||||
|
def comment(self, text: str) -> None:
|
||||||
|
self._write(f"{text}\n")
|
||||||
|
|
||||||
|
|
||||||
|
def var_dump(self, heading: str, var: Any) -> None:
|
||||||
|
self._write(f'{heading}:\n {self._python_var(var)}\n\n')
|
||||||
|
|
||||||
|
|
||||||
|
def sql(self, conn: AsyncConnection, statement: 'sa.Executable') -> None:
|
||||||
|
sqlstr = str(cast('sa.ClauseElement', statement)
|
||||||
|
.compile(conn.sync_engine, compile_kwargs={"literal_binds": True}))
|
||||||
|
sqlstr = '\n| '.join(textwrap.wrap(sqlstr, width=78))
|
||||||
|
self._write(f"| {sqlstr}\n\n")
|
||||||
|
|
||||||
|
|
||||||
|
def _python_var(self, var: Any) -> str:
|
||||||
|
return str(var)
|
||||||
|
|
||||||
|
|
||||||
|
def _write(self, text: str) -> None:
|
||||||
|
self.buffer.write(text)
|
||||||
|
|
||||||
|
|
||||||
logger: ContextVar[BaseLogger] = ContextVar('logger', default=BaseLogger())
|
logger: ContextVar[BaseLogger] = ContextVar('logger', default=BaseLogger())
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import datetime as dt
|
|||||||
|
|
||||||
import nominatim.api as napi
|
import nominatim.api as napi
|
||||||
from nominatim.db.sql_preprocessor import SQLPreprocessor
|
from nominatim.db.sql_preprocessor import SQLPreprocessor
|
||||||
|
import nominatim.api.logging as loglib
|
||||||
|
|
||||||
class APITester:
|
class APITester:
|
||||||
|
|
||||||
@@ -138,6 +139,8 @@ def apiobj(temp_db_with_extensions, temp_db_conn, monkeypatch):
|
|||||||
SQLPreprocessor(temp_db_conn, testapi.api.config)\
|
SQLPreprocessor(temp_db_conn, testapi.api.config)\
|
||||||
.run_sql_file(temp_db_conn, 'functions/address_lookup.sql')
|
.run_sql_file(temp_db_conn, 'functions/address_lookup.sql')
|
||||||
|
|
||||||
|
loglib.set_log_output('text')
|
||||||
yield testapi
|
yield testapi
|
||||||
|
print(loglib.get_and_disable())
|
||||||
|
|
||||||
testapi.api.close()
|
testapi.api.close()
|
||||||
|
|||||||
Reference in New Issue
Block a user