|
|
@ -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)) |
|
|
|