summaryrefslogtreecommitdiff
path: root/sphinx/versioning.py
diff options
context:
space:
mode:
authorDaniel Neuhäuser <ich@danielneuhaeuser.de>2010-08-16 08:10:14 +0200
committerDaniel Neuhäuser <ich@danielneuhaeuser.de>2010-08-16 08:10:14 +0200
commit36a0aa1667639818a39d43c79bceaa7ccee0392a (patch)
tree617997d9ced8b9b07a590a5ae6968567aa000bff /sphinx/versioning.py
parente68b1cacd077f49bafa84b95103945b19910993c (diff)
downloadsphinx-git-36a0aa1667639818a39d43c79bceaa7ccee0392a.tar.gz
Optimized further and added several comments explaining the merging algorithm
Diffstat (limited to 'sphinx/versioning.py')
-rw-r--r--sphinx/versioning.py38
1 files changed, 35 insertions, 3 deletions
diff --git a/sphinx/versioning.py b/sphinx/versioning.py
index 5f3254554..9a7cb2da6 100644
--- a/sphinx/versioning.py
+++ b/sphinx/versioning.py
@@ -13,6 +13,10 @@ from uuid import uuid4
from operator import itemgetter
from collections import defaultdict
from itertools import product
+try:
+ from itertools import izip_longest as zip_longest
+except ImportError:
+ from itertools import zip_longest
from sphinx.util import PeekableIterator
@@ -42,12 +46,32 @@ def merge_doctrees(old, new, condition):
:param condition:
A callable which returns either ``True`` or ``False`` for a given node.
"""
- old_nodes = old.traverse(condition)
- new_nodes = new.traverse(condition)
+ old_iter = old.traverse(condition)
+ new_iter = new.traverse(condition)
+ old_nodes = []
+ new_nodes = []
ratios = defaultdict(list)
seen = set()
+ # compare the nodes each doctree in order
+ for old_node, new_node in zip_longest(old_iter, new_iter):
+ if old_node is None:
+ new_nodes.append(new_node)
+ continue
+ if new_node is None:
+ old_nodes.append(old_node)
+ continue
+ ratio = get_ratio(old_node.rawsource, new_node.rawsource)
+ if ratio == 0:
+ new_node.uid = old_node.uid
+ seen.add(new_node)
+ else:
+ ratios[old_node, new_node] = ratio
+ old_nodes.append(old_node)
+ new_nodes.append(new_node)
+ # calculate the ratios for each unequal pair of nodes, should we stumble
+ # on a pair which is equal we set the uid and add it to the seen ones
for old_node, new_node in product(old_nodes, new_nodes):
- if new_node in seen:
+ if new_node in seen or (old_node, new_node) in ratios:
continue
ratio = get_ratio(old_node.rawsource, new_node.rawsource)
if ratio == 0:
@@ -55,6 +79,9 @@ def merge_doctrees(old, new, condition):
seen.add(new_node)
else:
ratios[old_node, new_node] = ratio
+ # choose the old node with the best ratio for each new node and set the uid
+ # as long as the ratio is under a certain value, in which case we consider
+ # them not changed but different
ratios = sorted(ratios.iteritems(), key=itemgetter(1))
for (old_node, new_node), ratio in ratios:
if new_node in seen:
@@ -66,6 +93,11 @@ def merge_doctrees(old, new, condition):
else:
new_node.uid = uuid4().hex
yield new_node
+ # create new uuids for any new node we left out earlier, this happens
+ # if one or more nodes are simply added.
+ for new_node in set(new_nodes) - seen:
+ new_node.uid = uuid4().hex
+ yield new_node
def get_ratio(old, new):
"""