Merge branch 'release/0.2.0'
* release/0.2.0: Improve release metadata Add handling for multiple IP occurrences Format IP lists as tables Fix IP address sorting Bump version number Fix grammar mistake Don't add GPL to long_description
This commit is contained in:
commit
88ffa4fbeb
5 changed files with 108 additions and 31 deletions
25
README.rst
25
README.rst
|
@ -1,3 +1,4 @@
|
||||||
|
==================
|
||||||
jandd.sphinxext.ip
|
jandd.sphinxext.ip
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
@ -5,10 +6,30 @@ This is an IP address extension for `Sphinx`_. The extension provides a domain
|
||||||
*ip* that allows marking IPv4 and IPv6 addresses in documentation and contains
|
*ip* that allows marking IPv4 and IPv6 addresses in documentation and contains
|
||||||
directives to collect information regarding IP addresses in IP ranges.
|
directives to collect information regarding IP addresses in IP ranges.
|
||||||
|
|
||||||
|
.. _Sphinx: http://www.sphinx-doc.org/
|
||||||
|
|
||||||
|
Development
|
||||||
|
===========
|
||||||
|
|
||||||
|
The extension is developed in a git repository that can be cloned by running::
|
||||||
|
|
||||||
|
git clone https://git.dittberner.info/sphinxext-ip.git
|
||||||
|
|
||||||
|
A repository browser is available at
|
||||||
|
https://git.dittberner.info/?p=sphinxext-ip.git.
|
||||||
|
|
||||||
Contributors
|
Contributors
|
||||||
------------
|
============
|
||||||
|
|
||||||
* `Jan Dittberner`_
|
* `Jan Dittberner`_
|
||||||
|
|
||||||
.. _Jan Dittberner: https://jan.dittberner.info/
|
.. _Jan Dittberner: https://jan.dittberner.info/
|
||||||
.. _Sphinx: http://www.sphinx-doc.org/
|
|
||||||
|
Changes
|
||||||
|
=======
|
||||||
|
|
||||||
|
0.2.0 - 2016-05-04
|
||||||
|
------------------
|
||||||
|
|
||||||
|
* display IP address lists as tables
|
||||||
|
* sort IP address lists numericaly
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
:copyright: Copyright (c) 2016 Jan Dittberner
|
:copyright: Copyright (c) 2016 Jan Dittberner
|
||||||
:license: GPLv3+, see COPYING file for details.
|
:license: GPLv3+, see COPYING file for details.
|
||||||
"""
|
"""
|
||||||
__version__ = '0.1.1'
|
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
@ -24,15 +23,20 @@ from sphinx.locale import l_
|
||||||
from sphinx.roles import XRefRole
|
from sphinx.roles import XRefRole
|
||||||
from sphinx.util.nodes import make_refnode
|
from sphinx.util.nodes import make_refnode
|
||||||
|
|
||||||
|
__version__ = '0.2.0'
|
||||||
|
|
||||||
|
|
||||||
def ip_object_anchor(typ, path):
|
def ip_object_anchor(typ, path):
|
||||||
path = re.sub(r'[.:/]', '-', path)
|
path = re.sub(r'[.:/]', '-', path)
|
||||||
return typ.lower() + '-' + path
|
return typ.lower() + '-' + path
|
||||||
|
|
||||||
|
|
||||||
class ip_node(nodes.Inline, nodes.TextElement): pass
|
class ip_node(nodes.Inline, nodes.TextElement):
|
||||||
|
pass
|
||||||
|
|
||||||
class ip_range(nodes.General, nodes.Element): pass
|
|
||||||
|
class ip_range(nodes.General, nodes.Element):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class IPXRefRole(XRefRole):
|
class IPXRefRole(XRefRole):
|
||||||
|
@ -42,7 +46,7 @@ class IPXRefRole(XRefRole):
|
||||||
def __init__(self, method, index_type, **kwargs):
|
def __init__(self, method, index_type, **kwargs):
|
||||||
self.method = method
|
self.method = method
|
||||||
self.index_type = index_type
|
self.index_type = index_type
|
||||||
innernodeclass=None
|
innernodeclass = None
|
||||||
if method in ('v4', 'v6'):
|
if method in ('v4', 'v6'):
|
||||||
innernodeclass = ip_node
|
innernodeclass = ip_node
|
||||||
super(IPXRefRole, self).__init__(
|
super(IPXRefRole, self).__init__(
|
||||||
|
@ -230,36 +234,85 @@ def process_ips(app, doctree):
|
||||||
node.replace_self(replacement)
|
node.replace_self(replacement)
|
||||||
|
|
||||||
|
|
||||||
def sort_ip_info(item):
|
def sort_ip(item):
|
||||||
return item['ip']
|
return Network(item).ip
|
||||||
|
|
||||||
|
|
||||||
|
def create_table_row(rowdata):
|
||||||
|
row = nodes.row()
|
||||||
|
for cell in rowdata:
|
||||||
|
entry = nodes.entry()
|
||||||
|
row += entry
|
||||||
|
entry += cell
|
||||||
|
return row
|
||||||
|
|
||||||
|
|
||||||
def process_ip_nodes(app, doctree, fromdocname):
|
def process_ip_nodes(app, doctree, fromdocname):
|
||||||
env = app.builder.env
|
env = app.builder.env
|
||||||
domaindata = env.domaindata[IPDomain.name]
|
domaindata = env.domaindata[IPDomain.name]
|
||||||
|
|
||||||
|
header = (l_('IP address'), l_('Used by'))
|
||||||
|
colwidths = (1, 3)
|
||||||
|
|
||||||
for node in doctree.traverse(ip_range):
|
for node in doctree.traverse(ip_range):
|
||||||
content = []
|
content = []
|
||||||
net = Network(node['rangespec'])
|
net = Network(node['rangespec'])
|
||||||
for ip_info in sorted(domaindata['ips'], key=sort_ip_info):
|
ips = {}
|
||||||
if ip_info['ip'] in net:
|
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))
|
||||||
|
table += tgroup
|
||||||
|
for colwidth in colwidths:
|
||||||
|
tgroup += nodes.colspec(colwidth=colwidth)
|
||||||
|
thead = nodes.thead()
|
||||||
|
tgroup += thead
|
||||||
|
thead += create_table_row([
|
||||||
|
nodes.paragraph(text=label) for label in header])
|
||||||
|
tbody = nodes.tbody()
|
||||||
|
tgroup += tbody
|
||||||
|
for ip, ip_info in [
|
||||||
|
(ip, ips[ip]) for ip in sorted(ips, key=sort_ip)
|
||||||
|
]:
|
||||||
para = nodes.paragraph()
|
para = nodes.paragraph()
|
||||||
para += nodes.literal('', ip_info['ip'])
|
para += nodes.literal('', ip)
|
||||||
ids = ip_object_anchor(ip_info['typ'], ip_info['ip'])
|
refnode = nodes.paragraph()
|
||||||
para['ids'].append(ids)
|
refuris = set()
|
||||||
domaindata[ip_info['typ']][ids] = (fromdocname, '')
|
refnodes = []
|
||||||
newnode = nodes.reference('', '', internal=True)
|
for item in ip_info:
|
||||||
try:
|
ids = ip_object_anchor(item['typ'], item['ip'])
|
||||||
newnode['refuri'] = app.builder.get_relative_uri(
|
if ids not in para['ids']:
|
||||||
fromdocname, ip_info['docname'])
|
para['ids'].append(ids)
|
||||||
except NoUri:
|
|
||||||
pass
|
domaindata[item['typ']][ids] = (fromdocname, '')
|
||||||
title = env.titles[ip_info['docname']]
|
newnode = nodes.reference('', '', internal=True)
|
||||||
innernode = nodes.Text(title.astext())
|
try:
|
||||||
newnode.append(innernode)
|
newnode['refuri'] = app.builder.get_relative_uri(
|
||||||
para += nodes.Text(" in ")
|
fromdocname, item['docname'])
|
||||||
para += newnode
|
if newnode['refuri'] in refuris:
|
||||||
content.append(para)
|
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:
|
||||||
|
para = nodes.paragraph(l_('No IP addresses in this range'))
|
||||||
|
content.append(para)
|
||||||
node.replace_self(content)
|
node.replace_self(content)
|
||||||
|
|
||||||
|
|
||||||
|
|
8
setup.py
8
setup.py
|
@ -2,14 +2,11 @@
|
||||||
|
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
version = '0.1.1'
|
version = '0.2.0'
|
||||||
|
|
||||||
with open('README.rst') as readme:
|
with open('README.rst') as readme:
|
||||||
description = readme.read() + "\n\n"
|
description = readme.read() + "\n\n"
|
||||||
|
|
||||||
with open('COPYING') as license:
|
|
||||||
description += license.read()
|
|
||||||
|
|
||||||
requires = ['Sphinx>=1.4', 'ipcalc>=1.99']
|
requires = ['Sphinx>=1.4', 'ipcalc>=1.99']
|
||||||
tests_requires = ['path.py>=8.2.1']
|
tests_requires = ['path.py>=8.2.1']
|
||||||
|
|
||||||
|
@ -17,12 +14,13 @@ tests_requires = ['path.py>=8.2.1']
|
||||||
setup(
|
setup(
|
||||||
author="Jan Dittberner",
|
author="Jan Dittberner",
|
||||||
author_email="jan@dittberner.info",
|
author_email="jan@dittberner.info",
|
||||||
description="IP address extensions for Sphinx",
|
description="IP address extension for Sphinx",
|
||||||
long_description=description,
|
long_description=description,
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
install_requires=requires,
|
install_requires=requires,
|
||||||
keywords="sphinx extension IP",
|
keywords="sphinx extension IP",
|
||||||
license="GPLv3+",
|
license="GPLv3+",
|
||||||
|
url="https://pypi.python.org/pypi/jandd.sphinxext.ip",
|
||||||
name="jandd.sphinxext.ip",
|
name="jandd.sphinxext.ip",
|
||||||
namespace_packages=['jandd', 'jandd.sphinxext'],
|
namespace_packages=['jandd', 'jandd.sphinxext'],
|
||||||
packages=find_packages(),
|
packages=find_packages(),
|
||||||
|
|
|
@ -13,6 +13,7 @@ Contents:
|
||||||
|
|
||||||
testpage1
|
testpage1
|
||||||
testpage2
|
testpage2
|
||||||
|
testpage3
|
||||||
|
|
||||||
|
|
||||||
Indices and tables
|
Indices and tables
|
||||||
|
|
4
tests/root/testpage3.rst
Normal file
4
tests/root/testpage3.rst
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
Test page 3
|
||||||
|
===========
|
||||||
|
|
||||||
|
This page contains :ip:v6:`2001:dead:beef::1` like :doc:`testpage2` does.
|
Loading…
Reference in a new issue