fix: add WebDiff class now that Diff lives in wuttjamaican
This commit is contained in:
parent
7e0b16c57d
commit
9a7488b063
3 changed files with 26 additions and 214 deletions
|
|
@ -29,60 +29,20 @@ import sqlalchemy as sa
|
|||
from pyramid.renderers import render
|
||||
from webhelpers2.html import HTML
|
||||
|
||||
from wuttjamaican.diffs import Diff
|
||||
|
||||
class Diff:
|
||||
|
||||
class WebDiff(Diff):
|
||||
"""
|
||||
Represent / display a basic "diff" between two data records.
|
||||
Simple diff class for the web app.
|
||||
|
||||
You must provide both the "old" and "new" data records, when
|
||||
constructing an instance of this class. Then call
|
||||
:meth:`render_html()` to display the diff table.
|
||||
|
||||
:param old_data: Dict of "old" data record.
|
||||
|
||||
:param new_data: Dict of "new" data record.
|
||||
|
||||
:param fields: Optional list of field names. If not specified,
|
||||
will be derived from the data records.
|
||||
|
||||
:param nature: What sort of diff is being represented; must be one
|
||||
of: ``("create", "update", "delete")``
|
||||
|
||||
:param old_color: Background color to display for "old/deleted"
|
||||
field data, when applicable.
|
||||
|
||||
:param new_color: Background color to display for "new/created"
|
||||
field data, when applicable.
|
||||
This is based on the
|
||||
:class:`~wuttjamaican:wuttjamaican.diffs.Diff` class; it just
|
||||
tweaks :meth:`render_html()` to use the web template lookup
|
||||
engine.
|
||||
"""
|
||||
|
||||
def __init__( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
||||
self,
|
||||
old_data: dict,
|
||||
new_data: dict,
|
||||
fields: list = None,
|
||||
nature="update",
|
||||
old_color="#ffebe9",
|
||||
new_color="#dafbe1",
|
||||
):
|
||||
self.old_data = old_data
|
||||
self.new_data = new_data
|
||||
self.columns = ["field name", "old value", "new value"]
|
||||
self.fields = fields or self.make_fields()
|
||||
self.nature = nature
|
||||
self.old_color = old_color
|
||||
self.new_color = new_color
|
||||
|
||||
def make_fields(self): # pylint: disable=missing-function-docstring
|
||||
return sorted(set(self.old_data) | set(self.new_data), key=lambda x: x.lower())
|
||||
|
||||
def old_value(self, field): # pylint: disable=missing-function-docstring
|
||||
return self.old_data.get(field)
|
||||
|
||||
def new_value(self, field): # pylint: disable=missing-function-docstring
|
||||
return self.new_data.get(field)
|
||||
|
||||
def values_differ(self, field): # pylint: disable=missing-function-docstring
|
||||
return self.new_value(field) != self.old_value(field)
|
||||
cell_padding = None
|
||||
|
||||
def render_html(self, template="/diff.mako", **kwargs):
|
||||
"""
|
||||
|
|
@ -98,69 +58,25 @@ class Diff:
|
|||
"""
|
||||
context = kwargs
|
||||
context["diff"] = self
|
||||
return HTML.literal(render(template, context))
|
||||
|
||||
def render_field_row(self, field): # pylint: disable=missing-function-docstring
|
||||
is_diff = self.values_differ(field)
|
||||
|
||||
td_field = HTML.tag("td", class_="field", c=field)
|
||||
|
||||
td_old_value = HTML.tag(
|
||||
"td",
|
||||
c=self.render_old_value(field),
|
||||
**self.get_old_value_attrs(is_diff),
|
||||
)
|
||||
|
||||
td_new_value = HTML.tag(
|
||||
"td",
|
||||
c=self.render_new_value(field),
|
||||
**self.get_new_value_attrs(is_diff),
|
||||
)
|
||||
|
||||
return HTML.tag("tr", c=[td_field, td_old_value, td_new_value])
|
||||
|
||||
def render_old_value(self, field): # pylint: disable=missing-function-docstring
|
||||
value = self.old_value(field)
|
||||
return repr(value)
|
||||
|
||||
def render_new_value(self, field): # pylint: disable=missing-function-docstring
|
||||
value = self.new_value(field)
|
||||
return repr(value)
|
||||
|
||||
def get_old_value_attrs( # pylint: disable=missing-function-docstring
|
||||
self, is_diff
|
||||
):
|
||||
attrs = {}
|
||||
if self.nature == "update" and is_diff:
|
||||
attrs["style"] = f"background-color: {self.old_color};"
|
||||
elif self.nature == "delete":
|
||||
attrs["style"] = f"background-color: {self.old_color};"
|
||||
return attrs
|
||||
|
||||
def get_new_value_attrs( # pylint: disable=missing-function-docstring
|
||||
self, is_diff
|
||||
):
|
||||
attrs = {}
|
||||
if self.nature == "create":
|
||||
attrs["style"] = f"background-color: {self.new_color};"
|
||||
elif self.nature == "update" and is_diff:
|
||||
attrs["style"] = f"background-color: {self.new_color};"
|
||||
return attrs
|
||||
html = render(template, context)
|
||||
return HTML.literal(html)
|
||||
|
||||
|
||||
class VersionDiff(Diff):
|
||||
class VersionDiff(WebDiff):
|
||||
"""
|
||||
Special diff class for use with version history views. While
|
||||
based on :class:`Diff`, this class uses a different signature for
|
||||
the constructor.
|
||||
based on :class:`WebDiff`, this class uses a different signature
|
||||
for the constructor.
|
||||
|
||||
:param version: Reference to a Continuum version record (object).
|
||||
:param config: The app :term:`config object`.
|
||||
|
||||
:param version: Reference to a Continuum version record object.
|
||||
|
||||
:param \\**kwargs: Remaining kwargs are passed as-is to the
|
||||
:class:`Diff` constructor.
|
||||
:class:`WebDiff` constructor.
|
||||
"""
|
||||
|
||||
def __init__(self, version, **kwargs):
|
||||
def __init__(self, config, version, **kwargs):
|
||||
import sqlalchemy_continuum as continuum # pylint: disable=import-outside-toplevel
|
||||
from wutta_continuum.util import ( # pylint: disable=import-outside-toplevel
|
||||
render_operation_type,
|
||||
|
|
@ -195,7 +111,7 @@ class VersionDiff(Diff):
|
|||
old_data[field] = getattr(version.previous, field)
|
||||
new_data[field] = getattr(version, field)
|
||||
|
||||
super().__init__(old_data, new_data, **kwargs)
|
||||
super().__init__(config, old_data, new_data, **kwargs)
|
||||
|
||||
def get_default_fields(self): # pylint: disable=missing-function-docstring
|
||||
fields = sorted(self.version_mapper.columns.keys())
|
||||
|
|
|
|||
|
|
@ -1269,7 +1269,7 @@ class MasterView(View): # pylint: disable=too-many-public-methods
|
|||
)
|
||||
|
||||
version_diffs = [
|
||||
VersionDiff(version)
|
||||
VersionDiff(self.config, version)
|
||||
for version in self.get_relevant_versions(txn, instance)
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -4,114 +4,10 @@ from wuttaweb import diffs as mod
|
|||
from wuttaweb.testing import WebTestCase, VersionWebTestCase
|
||||
|
||||
|
||||
# nb. using WebTestCase here only for mako support in render_html()
|
||||
class TestDiff(WebTestCase):
|
||||
class TestWebDiff(WebTestCase):
|
||||
|
||||
def make_diff(self, *args, **kwargs):
|
||||
return mod.Diff(*args, **kwargs)
|
||||
|
||||
def test_constructor(self):
|
||||
old_data = {"foo": "bar"}
|
||||
new_data = {"foo": "baz"}
|
||||
diff = self.make_diff(old_data, new_data, fields=["foo"])
|
||||
self.assertEqual(diff.fields, ["foo"])
|
||||
|
||||
def test_make_fields(self):
|
||||
old_data = {"foo": "bar"}
|
||||
new_data = {"foo": "bar", "baz": "zer"}
|
||||
# nb. this calls make_fields()
|
||||
diff = self.make_diff(old_data, new_data)
|
||||
# TODO: should the fields be cumulative? or just use new_data?
|
||||
self.assertEqual(diff.fields, ["baz", "foo"])
|
||||
|
||||
def test_values(self):
|
||||
old_data = {"foo": "bar"}
|
||||
new_data = {"foo": "baz"}
|
||||
diff = self.make_diff(old_data, new_data)
|
||||
self.assertEqual(diff.old_value("foo"), "bar")
|
||||
self.assertEqual(diff.new_value("foo"), "baz")
|
||||
|
||||
def test_values_differ(self):
|
||||
old_data = {"foo": "bar"}
|
||||
new_data = {"foo": "baz"}
|
||||
diff = self.make_diff(old_data, new_data)
|
||||
self.assertTrue(diff.values_differ("foo"))
|
||||
|
||||
old_data = {"foo": "bar"}
|
||||
new_data = {"foo": "bar"}
|
||||
diff = self.make_diff(old_data, new_data)
|
||||
self.assertFalse(diff.values_differ("foo"))
|
||||
|
||||
def test_render_values(self):
|
||||
old_data = {"foo": "bar"}
|
||||
new_data = {"foo": "baz"}
|
||||
diff = self.make_diff(old_data, new_data)
|
||||
self.assertEqual(diff.render_old_value("foo"), "'bar'")
|
||||
self.assertEqual(diff.render_new_value("foo"), "'baz'")
|
||||
|
||||
def test_get_old_value_attrs(self):
|
||||
|
||||
# no change
|
||||
old_data = {"foo": "bar"}
|
||||
new_data = {"foo": "bar"}
|
||||
diff = self.make_diff(old_data, new_data, nature="update")
|
||||
self.assertEqual(diff.get_old_value_attrs(False), {})
|
||||
|
||||
# update
|
||||
old_data = {"foo": "bar"}
|
||||
new_data = {"foo": "baz"}
|
||||
diff = self.make_diff(old_data, new_data, nature="update")
|
||||
self.assertEqual(
|
||||
diff.get_old_value_attrs(True),
|
||||
{"style": f"background-color: {diff.old_color};"},
|
||||
)
|
||||
|
||||
# delete
|
||||
old_data = {"foo": "bar"}
|
||||
new_data = {}
|
||||
diff = self.make_diff(old_data, new_data, nature="delete")
|
||||
self.assertEqual(
|
||||
diff.get_old_value_attrs(True),
|
||||
{"style": f"background-color: {diff.old_color};"},
|
||||
)
|
||||
|
||||
def test_get_new_value_attrs(self):
|
||||
|
||||
# no change
|
||||
old_data = {"foo": "bar"}
|
||||
new_data = {"foo": "bar"}
|
||||
diff = self.make_diff(old_data, new_data, nature="update")
|
||||
self.assertEqual(diff.get_new_value_attrs(False), {})
|
||||
|
||||
# update
|
||||
old_data = {"foo": "bar"}
|
||||
new_data = {"foo": "baz"}
|
||||
diff = self.make_diff(old_data, new_data, nature="update")
|
||||
self.assertEqual(
|
||||
diff.get_new_value_attrs(True),
|
||||
{"style": f"background-color: {diff.new_color};"},
|
||||
)
|
||||
|
||||
# create
|
||||
old_data = {}
|
||||
new_data = {"foo": "bar"}
|
||||
diff = self.make_diff(old_data, new_data, nature="create")
|
||||
self.assertEqual(
|
||||
diff.get_new_value_attrs(True),
|
||||
{"style": f"background-color: {diff.new_color};"},
|
||||
)
|
||||
|
||||
def test_render_field_row(self):
|
||||
old_data = {"foo": "bar"}
|
||||
new_data = {"foo": "baz"}
|
||||
diff = self.make_diff(old_data, new_data)
|
||||
row = diff.render_field_row("foo")
|
||||
self.assertIn("<tr>", row)
|
||||
self.assertIn("'bar'", row)
|
||||
self.assertIn(f'style="background-color: {diff.old_color};"', row)
|
||||
self.assertIn("'baz'", row)
|
||||
self.assertIn(f'style="background-color: {diff.new_color};"', row)
|
||||
self.assertIn("</tr>", row)
|
||||
return mod.WebDiff(self.config, *args, **kwargs)
|
||||
|
||||
def test_render_html(self):
|
||||
old_data = {"foo": "bar"}
|
||||
|
|
@ -121,9 +17,9 @@ class TestDiff(WebTestCase):
|
|||
self.assertIn("<table", html)
|
||||
self.assertIn("<tr>", html)
|
||||
self.assertIn("'bar'", html)
|
||||
self.assertIn(f'style="background-color: {diff.old_color};"', html)
|
||||
self.assertIn(f'style="background-color: {diff.old_color}"', html)
|
||||
self.assertIn("'baz'", html)
|
||||
self.assertIn(f'style="background-color: {diff.new_color};"', html)
|
||||
self.assertIn(f'style="background-color: {diff.new_color}"', html)
|
||||
self.assertIn("</tr>", html)
|
||||
self.assertIn("</table>", html)
|
||||
|
||||
|
|
@ -131,7 +27,7 @@ class TestDiff(WebTestCase):
|
|||
class TestVersionDiff(VersionWebTestCase):
|
||||
|
||||
def make_diff(self, *args, **kwargs):
|
||||
return mod.VersionDiff(*args, **kwargs)
|
||||
return mod.VersionDiff(self.config, *args, **kwargs)
|
||||
|
||||
def test_constructor(self):
|
||||
import sqlalchemy_continuum as continuum
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue