Compare commits

...

2 Commits

Author SHA1 Message Date
Jan Dittberner 7acff11695 Release 0.5.1 11 months ago
Jan Dittberner d1a151f8bd Fix anchor links 11 months ago
  1. 5
      CHANGES.rst
  2. 66
      jandd/sphinxext/ip.py
  3. 2
      setup.cfg
  4. 4
      tests/root/conf.py
  5. 6
      tests/test_ip.py

5
CHANGES.rst

@ -1,6 +1,11 @@
Changes
=======
0.5.1 - 2021-09-04
------------------
* fix anchors in links
0.5.0 - 2021-09-04
------------------

66
jandd/sphinxext/ip.py

@ -8,7 +8,7 @@
:copyright: Copyright (c) 2016-2021 Jan Dittberner
:license: GPLv3+, see COPYING file for details.
"""
__version__ = "0.5.0"
__version__ = "0.5.1"
from collections import defaultdict
from typing import Iterable, List, Optional, Tuple
@ -62,12 +62,13 @@ class IPV4RangeDirective(IPRangeDirective):
title_prefix = _("IPv4 range")
def add_target_and_index(self, name: T, sig: str, signode: desc_signature) -> None:
signode["ids"].append("ip4_range" + "-" + sig)
anchor = "ip-ipv4range-{0}".format(sig)
signode["ids"].append(anchor)
ips = self.env.get_domain("ip")
ips.add_ip4_range(sig)
idx_text = "{}; {}".format(self.title_prefix, name)
self.indexnode["entries"] = [
("single", idx_text, name, "", None),
("single", idx_text, anchor, "", None),
]
@ -75,12 +76,13 @@ class IPV6RangeDirective(IPRangeDirective):
title_prefix = _("IPv6 range")
def add_target_and_index(self, name: T, sig: str, signode: desc_signature) -> None:
signode["ids"].append("ip6_range" + "-" + sig)
anchor = "ip-ipv6range-{0}".format(sig)
signode["ids"].append(anchor)
ips = self.env.get_domain("ip")
ips.add_ip6_range(sig)
idx_text = "{}; {}".format(self.title_prefix, name)
self.indexnode["entries"] = [
("single", idx_text, name, "", None),
("single", idx_text, anchor, "", None),
]
@ -121,7 +123,7 @@ class IPXRefRole(XRefRole):
node_list, message = super().result_nodes(document, env, node, is_ref)
ip = env.get_domain("ip")
if self.reftype in ["v4", "v6"] and self.target not in ip.data["ips"]:
if self.reftype in ["v4", "v6"] and self.target not in ip.data["ip_dict"]:
return node_list, message
if (
self.reftype in ["v4range", "v6range"]
@ -130,7 +132,11 @@ class IPXRefRole(XRefRole):
return node_list, message
index_node = addnodes.index()
target_id = "index-{}".format(env.new_serialno("index"))
target_id = "ip-{}-{}".format(self.reftype, env.new_serialno("index"))
if self.reftype in ["v4", "v6"]:
ip.add_ip_address_anchor(self.target, env.docname, target_id)
target_node = nodes.target("", "", ids=[target_id])
doc_title = next(d for d in document.traverse(nodes.title)).astext()
@ -175,10 +181,9 @@ class IPDomain(Domain):
initial_data = {
"range_nodes": [],
"ip_refs": [],
"ip_refs": defaultdict(list),
"range_refs": [],
"ranges": defaultdict(list),
"ips": defaultdict(list),
"ip_dict": {},
}
@ -218,23 +223,15 @@ class IPDomain(Domain):
self._add_ip_address_reference("v6", ip_address)
def _add_ip_address_reference(self, family, sig):
name = "ip{}.{}".format(family, sig)
anchor = "ip-ip{}-{}".format(family, sig)
try:
self.data["ip_dict"][sig] = IP(sig)
except ValueError as e:
logger.error("invalid ip address '%s': %s", sig, e)
def add_ip_address_anchor(self, sig, docname, anchor):
try:
ip = IP(sig)
self.data["ip_refs"].append(
(
name,
sig,
"IP{}".format(family),
str(ip),
self.env.docname,
anchor,
0,
)
)
self.data["ips"][sig].append((ip, self.env.docname, anchor))
self.data["ip_dict"][sig] = ip
self.data["ip_refs"][sig].append((ip, docname, anchor))
except ValueError as e:
logger.error("invalid ip address '%s': %s", sig, e)
@ -276,13 +273,25 @@ class IPDomain(Domain):
contnode: nodes.Element,
) -> Optional[nodes.Element]:
match = []
def address_tuple(docname, anchor, ip_range) -> Tuple[str, str, str]:
return (
docname,
anchor,
_(
"IPv{0} range {1}".format(
ip_range.version(), ip_range.to_compressed()
)
),
)
if typ in ("v4", "v6"):
# reference to IP range
if target not in self.data["ip_dict"]:
# invalid ip address
raise NoUri(target)
match = [
(docname, anchor)
address_tuple(docname, anchor, ip_range)
for ip_range, docname, anchor in [
r
for range_nodes in self.data["ranges"].values()
@ -293,7 +302,7 @@ class IPDomain(Domain):
elif typ in ("v4range", "v6range"):
if target in self.data["ranges"]:
match = [
(docname, anchor)
address_tuple(docname, anchor, ip_range)
for ip_range, docname, anchor in [
range_nodes for range_nodes in self.data["ranges"][target]
]
@ -301,8 +310,9 @@ class IPDomain(Domain):
if len(match) > 0:
todocname = match[0][0]
targ = match[0][1]
title = match[0][2]
return make_refnode(builder, fromdocname, todocname, targ, contnode, targ)
return make_refnode(builder, fromdocname, todocname, targ, contnode, title)
else:
logger.error("found no link target for %s", target)
return None
@ -319,7 +329,7 @@ def process_ip_nodes(app, doctree, fromdocname):
content = []
net = Network(node["range_spec"])
addresses = defaultdict(list)
for ip_address_sig, refs in ips.data["ips"].items():
for ip_address_sig, refs in ips.data["ip_refs"].items():
for ip_address, todocname, anchor in refs:
if ip_address in net:
addresses[ip_address_sig].append((ip_address, todocname, anchor))

2
setup.cfg

@ -17,7 +17,7 @@ keywords = sphinx, extension, IP
license = GPLv3+
license_file = COPYING
platforms = any
version = 0.5.0
version = 0.5.1
classifiers =
Development Status :: 5 - Production/Stable
Framework :: Sphinx :: Extension

4
tests/root/conf.py

@ -55,9 +55,9 @@ author = "Jan Dittberner"
# built documents.
#
# The short X.Y version.
version = "0.5.0"
version = "0.5.1"
# The full version, including alpha/beta/rc tags.
release = version + "-dev"
release = version
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

6
tests/test_ip.py

@ -32,7 +32,7 @@ class TestIPExtension(unittest.TestCase):
self.assertIn("range_refs", ipdomdata)
self.assertIn("range_nodes", ipdomdata)
self.assertIn("ranges", ipdomdata)
self.assertIn("ips", ipdomdata)
self.assertIn("ip_dict", ipdomdata)
def find_in_index(self, entry):
indexentries = self.app.env.get_domain("index").entries
@ -43,14 +43,14 @@ class TestIPExtension(unittest.TestCase):
self.fail("%s not found in index" % entry)
def test_ip4_addresses(self):
ips = self.app.env.domaindata["ip"]["ips"]
ips = self.app.env.domaindata["ip"]["ip_refs"]
for ip in IP4_ADDRESSES:
self.assertIn(ip, ips)
self.find_in_index("IPv4 address; %s" % ip)
self.find_in_index("%s; Test page 2" % ip)
def test_ip6_addresses(self):
ips = self.app.env.domaindata["ip"]["ips"]
ips = self.app.env.domaindata["ip"]["ip_refs"]
for ip in IP6_ADDRESSES:
self.assertIn(ip, ips)
self.find_in_index("IPv6 address; %s" % ip)

Loading…
Cancel
Save