From dd419f4ae655363e0fecfcfc615b011a4e196d0d Mon Sep 17 00:00:00 2001
From: Jan Dittberner <jan@dittberner.info>
Date: Wed, 4 May 2016 13:19:17 +0200
Subject: [PATCH] Add handling for multiple IP occurrences

This commit adds handling of multiple occurrences of the same IP address
in one or more pages.
---
 jandd/sphinxext/ip.py    | 60 ++++++++++++++++++++++++++--------------
 tests/root/index.rst     |  1 +
 tests/root/testpage3.rst |  4 +++
 3 files changed, 44 insertions(+), 21 deletions(-)
 create mode 100644 tests/root/testpage3.rst

diff --git a/jandd/sphinxext/ip.py b/jandd/sphinxext/ip.py
index 24b6672..0c71bda 100644
--- a/jandd/sphinxext/ip.py
+++ b/jandd/sphinxext/ip.py
@@ -234,8 +234,8 @@ def process_ips(app, doctree):
         node.replace_self(replacement)
 
 
-def sort_ip_info(item):
-    return Network(item['ip']).ip
+def sort_ip(item):
+    return Network(item).ip
 
 
 def create_table_row(rowdata):
@@ -257,9 +257,14 @@ def process_ip_nodes(app, doctree, fromdocname):
     for node in doctree.traverse(ip_range):
         content = []
         net = Network(node['rangespec'])
-        ips = [ip_info for ip_info in
-               sorted(domaindata['ips'], key=sort_ip_info)
-               if ip_info['ip'] in net]
+        ips = {}
+        for key, value in [
+            (ip_info['ip'], ip_info) for ip_info in
+            domaindata['ips'] if ip_info['ip'] in net
+        ]:
+            addrlist = ips.get(key, [])
+            addrlist.append(value)
+            ips[key] = addrlist
         if ips:
             table = nodes.table()
             tgroup = nodes.tgroup(cols=len(header))
@@ -272,24 +277,37 @@ def process_ip_nodes(app, doctree, fromdocname):
                 nodes.paragraph(text=label) for label in header])
             tbody = nodes.tbody()
             tgroup += tbody
-            for ip_info in ips:
+            for ip, ip_info in [
+                (ip, ips[ip]) for ip in sorted(ips, key=sort_ip)
+            ]:
                 para = nodes.paragraph()
-                para += nodes.literal('', ip_info['ip'])
-                ids = ip_object_anchor(ip_info['typ'], ip_info['ip'])
-                para['ids'].append(ids)
-
-                domaindata[ip_info['typ']][ids] = (fromdocname, '')
-                newnode = nodes.reference('', '', internal=True)
-                try:
-                    newnode['refuri'] = app.builder.get_relative_uri(
-                        fromdocname, ip_info['docname'])
-                except NoUri:
-                    pass
-                title = env.titles[ip_info['docname']]
-                innernode = nodes.Text(title.astext())
-                newnode.append(innernode)
+                para += nodes.literal('', ip)
                 refnode = nodes.paragraph()
-                refnode.append(newnode)
+                refuris = set()
+                refnodes = []
+                for item in ip_info:
+                    ids = ip_object_anchor(item['typ'], item['ip'])
+                    if ids not in para['ids']:
+                        para['ids'].append(ids)
+
+                    domaindata[item['typ']][ids] = (fromdocname, '')
+                    newnode = nodes.reference('', '', internal=True)
+                    try:
+                        newnode['refuri'] = app.builder.get_relative_uri(
+                            fromdocname, item['docname'])
+                        if newnode['refuri'] in refuris:
+                            continue
+                        refuris.add(newnode['refuri'])
+                    except NoUri:
+                        pass
+                    title = env.titles[item['docname']]
+                    innernode = nodes.Text(title.astext())
+                    newnode.append(innernode)
+                    refnodes.append(newnode)
+                for count in range(len(refnodes)):
+                    refnode.append(refnodes[count])
+                    if count < len(refnodes) - 1:
+                        refnode.append(nodes.Text(", "))
                 tbody += create_table_row([para, refnode])
             content.append(table)
         else:
diff --git a/tests/root/index.rst b/tests/root/index.rst
index 8ada3e1..4b2e15e 100644
--- a/tests/root/index.rst
+++ b/tests/root/index.rst
@@ -13,6 +13,7 @@ Contents:
 
    testpage1
    testpage2
+   testpage3
 
 
 Indices and tables
diff --git a/tests/root/testpage3.rst b/tests/root/testpage3.rst
new file mode 100644
index 0000000..ae38493
--- /dev/null
+++ b/tests/root/testpage3.rst
@@ -0,0 +1,4 @@
+Test page 3
+===========
+
+This page contains :ip:v6:`2001:dead:beef::1` like :doc:`testpage2` does.