-
Notifications
You must be signed in to change notification settings - Fork 486
/
helpers.py
85 lines (70 loc) · 3.01 KB
/
helpers.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
"""A number of useful helper functions to automate common tasks."""
from __future__ import unicode_literals
from django.contrib import admin
from django.contrib.admin.sites import NotRegistered
from django.utils.encoding import force_text
from reversion.admin import VersionAdmin
def patch_admin(model, admin_site=None):
"""
Enables version control with full admin integration for a model that has
already been registered with the django admin site.
This is excellent for adding version control to existing Django contrib
applications.
"""
admin_site = admin_site or admin.site
try:
ModelAdmin = admin_site._registry[model].__class__
except KeyError:
raise NotRegistered("The model {model} has not been registered with the admin site.".format(
model = model,
))
# Unregister existing admin class.
admin_site.unregister(model)
# Register patched admin class.
class PatchedModelAdmin(VersionAdmin, ModelAdmin):
pass
admin_site.register(model, PatchedModelAdmin)
# Patch generation methods, only available if the google-diff-match-patch
# library is installed.
#
# http://code.google.com/p/google-diff-match-patch/
try:
from diff_match_patch import diff_match_patch
except ImportError: # pragma: no cover
pass
else:
dmp = diff_match_patch()
def generate_diffs(old_version, new_version, field_name, cleanup):
"""Generates a diff array for the named field between the two versions."""
# Extract the text from the versions.
old_text = old_version.field_dict[field_name] or ""
new_text = new_version.field_dict[field_name] or ""
# Generate the patch.
diffs = dmp.diff_main(force_text(old_text), force_text(new_text))
if cleanup == "semantic":
dmp.diff_cleanupSemantic(diffs)
elif cleanup == "efficiency":
dmp.diff_cleanupEfficiency(diffs)
elif cleanup is None:
pass
else: # pragma: no cover
raise ValueError("cleanup parameter should be one of 'semantic', 'efficiency' or None.")
return diffs
def generate_patch(old_version, new_version, field_name, cleanup=None):
"""
Generates a text patch of the named field between the two versions.
The cleanup parameter can be None, "semantic" or "efficiency" to clean up the diff
for greater human readibility.
"""
diffs = generate_diffs(old_version, new_version, field_name, cleanup)
patch = dmp.patch_make(diffs)
return dmp.patch_toText(patch)
def generate_patch_html(old_version, new_version, field_name, cleanup=None):
"""
Generates a pretty html version of the differences between the named
field in two versions.
The cleanup parameter can be None, "semantic" or "efficiency" to clean up the diff
for greater human readibility.
"""
diffs = generate_diffs(old_version, new_version, field_name, cleanup)
return dmp.diff_prettyHtml(diffs)