Run through black and isort

This commit is contained in:
Jan Dittberner 2021-01-02 06:20:53 +01:00
parent 0af66c6964
commit fdb126996a
8 changed files with 297 additions and 252 deletions

View file

@ -1 +1 @@
__import__('pkg_resources').declare_namespace(__name__)
__import__("pkg_resources").declare_namespace(__name__)

View file

@ -1 +1 @@
__import__('pkg_resources').declare_namespace(__name__)
__import__("pkg_resources").declare_namespace(__name__)

View file

@ -11,11 +11,9 @@
import re
from ipcalc import Network
from docutils import nodes
from docutils.parsers.rst import Directive
from ipcalc import Network
from sphinx import addnodes
from sphinx.domains import Domain, ObjType
from sphinx.errors import NoUri
@ -24,15 +22,15 @@ from sphinx.roles import XRefRole
from sphinx.util import logging
from sphinx.util.nodes import make_refnode
__version__ = '0.3.0'
__version__ = "0.4.0"
logger = logging.getLogger(__name__)
def ip_object_anchor(typ, path):
path = re.sub(r'[.:/]', '-', path)
return typ.lower() + '-' + path
path = re.sub(r"[.:/]", "-", path)
return typ.lower() + "-" + path
class ip_node(nodes.Inline, nodes.TextElement):
@ -47,17 +45,16 @@ class IPXRefRole(XRefRole):
"""
Cross referencing role for the IP domain.
"""
def __init__(self, method, index_type, **kwargs):
self.method = method
self.index_type = index_type
innernodeclass = None
if method in ('v4', 'v6'):
if method in ("v4", "v6"):
innernodeclass = ip_node
super(IPXRefRole, self).__init__(
innernodeclass=innernodeclass, **kwargs)
super(IPXRefRole, self).__init__(innernodeclass=innernodeclass, **kwargs)
def __cal__(self, typ, rawtext, text, lineno, inliner,
options=None, content=None):
def __cal__(self, typ, rawtext, text, lineno, inliner, options=None, content=None):
if content is None:
content = []
if options is None:
@ -66,28 +63,31 @@ class IPXRefRole(XRefRole):
Network(text)
except ValueError as e:
env = inliner.document.settings.env
logger.warning("invalid ip address/range %s" % text, location=(env.docname, lineno))
logger.warning(
"invalid ip address/range %s" % text, location=(env.docname, lineno)
)
return [nodes.literal(text, text), []]
return super(IPXRefRole, self).__call__(
typ, rawtext, text, lineno, inliner, options, content)
typ, rawtext, text, lineno, inliner, options, content
)
def process_link(self, env, refnode, has_explicit_title, title, target):
domaindata = env.domaindata['ip']
domaindata = env.domaindata["ip"]
domaindata[self.method][target] = (target, refnode)
return title, target
def result_nodes(self, document, env, node, is_ref):
try:
node['typ'] = self.method
node["typ"] = self.method
indexnode = addnodes.index()
targetid = 'index-%s' % env.new_serialno('index')
targetnode = nodes.target('', '', ids=[targetid])
targetid = "index-%s" % env.new_serialno("index")
targetnode = nodes.target("", "", ids=[targetid])
doctitle = list(document.traverse(nodes.title))[0].astext()
idxtext = "%s; %s" % (node.astext(), doctitle)
idxtext2 = "%s; %s" % (self.index_type, node.astext())
indexnode['entries'] = [
('single', idxtext, targetid, '', None),
('single', idxtext2, targetid, '', None),
indexnode["entries"] = [
("single", idxtext, targetid, "", None),
("single", idxtext2, targetid, "", None),
]
return [indexnode, targetnode, node], []
except KeyError as e:
@ -104,20 +104,21 @@ class IPRange(Directive):
def handle_rangespec(self, node):
titlenode = nodes.title()
node.append(titlenode)
titlenode.append(nodes.inline('', self.get_prefix_title()))
titlenode.append(nodes.literal('', self.rangespec))
titlenode.append(nodes.inline("", self.get_prefix_title()))
titlenode.append(nodes.literal("", self.rangespec))
ids = ip_object_anchor(self.typ, self.rangespec)
node['ids'].append(ids)
node["ids"].append(ids)
self.env.domaindata[self.domain][self.typ][ids] = (
self.env.docname,
self.options.get('synopsis', ''))
self.options.get("synopsis", ""),
)
return ids
def run(self):
if ':' in self.name:
self.domain, self.objtype = self.name.split(':', 1)
if ":" in self.name:
self.domain, self.objtype = self.name.split(":", 1)
else:
self.domain, self.objtype = '', self.name
self.domain, self.objtype = "", self.name
self.env = self.state.document.settings.env
self.rangespec = self.arguments[0]
node = nodes.section()
@ -127,97 +128,98 @@ class IPRange(Directive):
else:
doctitle = list(self.state.document.traverse(nodes.title))[0].astext()
idx_text = "%s; %s" % (self.rangespec, doctitle)
self.indexnode = addnodes.index(entries=[
('single', idx_text, name, '', None),
('single', self.get_index_text(), name, '', None)
])
self.indexnode = addnodes.index(
entries=[
("single", idx_text, name, "", None),
("single", self.get_index_text(), name, "", None),
]
)
if self.content:
contentnode = nodes.paragraph('')
contentnode = nodes.paragraph("")
node.append(contentnode)
self.state.nested_parse(
self.content, self.content_offset, contentnode)
self.state.nested_parse(self.content, self.content_offset, contentnode)
iprange = ip_range()
node.append(iprange)
iprange['rangespec'] = self.rangespec
iprange["rangespec"] = self.rangespec
return [self.indexnode, node]
class IPv4Range(IPRange):
typ = 'v4range'
typ = "v4range"
def get_prefix_title(self):
return _('IPv4 address range ')
return _("IPv4 address range ")
def get_index_text(self):
return "%s; %s" % (_('IPv4 range'), self.rangespec)
return "%s; %s" % (_("IPv4 range"), self.rangespec)
class IPv6Range(IPRange):
typ = 'v6range'
typ = "v6range"
def get_prefix_title(self):
return _('IPv6 address range ')
return _("IPv6 address range ")
def get_index_text(self):
return "%s; %s" % (_('IPv6 range'), self.rangespec)
return "%s; %s" % (_("IPv6 range"), self.rangespec)
class IPDomain(Domain):
"""
IP address and range domain.
"""
name = 'ip'
label = 'IP addresses and ranges.'
name = "ip"
label = "IP addresses and ranges."
object_types = {
'v4': ObjType(_('v4'), 'v4', 'obj'),
'v6': ObjType(_('v6'), 'v6', 'obj'),
'v4range': ObjType(_('v4range'), 'v4range', 'obj'),
'v6range': ObjType(_('v6range'), 'v6range', 'obj'),
"v4": ObjType(_("v4"), "v4", "obj"),
"v6": ObjType(_("v6"), "v6", "obj"),
"v4range": ObjType(_("v4range"), "v4range", "obj"),
"v6range": ObjType(_("v6range"), "v6range", "obj"),
}
directives = {
'v4range': IPv4Range,
'v6range': IPv6Range,
"v4range": IPv4Range,
"v6range": IPv6Range,
}
roles = {
'v4': IPXRefRole('v4', _('IPv4 address')),
'v6': IPXRefRole('v6', _('IPv6 address')),
'v4range': IPXRefRole('v4range', _('IPv4 range')),
'v6range': IPXRefRole('v6range', _('IPv6 range')),
"v4": IPXRefRole("v4", _("IPv4 address")),
"v6": IPXRefRole("v6", _("IPv6 address")),
"v4range": IPXRefRole("v4range", _("IPv4 range")),
"v6range": IPXRefRole("v6range", _("IPv6 range")),
}
initial_data = {
'v4': {},
'v6': {},
'v4range': {},
'v6range': {},
'ips': [],
"v4": {},
"v6": {},
"v4range": {},
"v6range": {},
"ips": [],
}
def clear_doc(self, docname):
to_remove = []
for key, value in self.data['v4range'].items():
for key, value in self.data["v4range"].items():
if docname == value[0]:
to_remove.append(key)
for key in to_remove:
del self.data['v4range'][key]
del self.data["v4range"][key]
to_remove = []
for key, value in self.data['v6range'].items():
for key, value in self.data["v6range"].items():
if docname == value[0]:
to_remove.append(key)
for key in to_remove:
del self.data['v6range'][key]
self.data['ips'] = [
item for item in self.data['ips'] if item['docname'] != docname
del self.data["v6range"][key]
self.data["ips"] = [
item for item in self.data["ips"] if item["docname"] != docname
]
def resolve_xref(self, env, fromdocname, builder, typ, target, node,
contnode):
def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
key = ip_object_anchor(typ, target)
try:
info = self.data[typ][key]
@ -226,19 +228,20 @@ class IPDomain(Domain):
role = self.roles.get(typ)
if role is None:
return None
resnode = role.result_nodes(env.get_doctree(fromdocname),
env, node, True)[0][2]
resnode = role.result_nodes(env.get_doctree(fromdocname), env, node, True)[
0
][2]
if isinstance(resnode, addnodes.pending_xref):
text = node[0][0]
reporter = env.get_doctree(fromdocname).reporter
reporter.warning('Cannot resolve reference to %r' % text,
line=node.line)
reporter.warning(
"Cannot resolve reference to %r" % text, line=node.line
)
return node.children
return resnode
else:
title = typ.upper() + ' ' + target
return make_refnode(builder, fromdocname, info[0], key,
contnode, title)
title = typ.upper() + " " + target
return make_refnode(builder, fromdocname, info[0], key, contnode, title)
@property
def items(self):
@ -257,13 +260,15 @@ def process_ips(app, doctree):
for node in doctree.traverse(ip_node):
ip = node.astext()
domaindata['ips'].append({
'docname': env.docname,
'source': node.parent.source or env.doc2path(env.docname),
'lineno': node.parent.line,
'ip': ip,
'typ': node.parent['typ'],
})
domaindata["ips"].append(
{
"docname": env.docname,
"source": node.parent.source or env.doc2path(env.docname),
"lineno": node.parent.line,
"ip": ip,
"typ": node.parent["typ"],
}
)
replacement = nodes.literal(ip, ip)
node.replace_self(replacement)
@ -285,17 +290,14 @@ def process_ip_nodes(app, doctree, fromdocname):
env = app.builder.env
domaindata = env.domaindata[IPDomain.name]
header = (_('IP address'), _('Used by'))
header = (_("IP address"), _("Used by"))
colwidths = (1, 3)
for node in doctree.traverse(ip_range):
content = []
net = Network(node['rangespec'])
net = Network(node["rangespec"])
ips = {}
for key, value in [
(ip_info['ip'], ip_info) for ip_info in
domaindata['ips']
]:
for key, value in [(ip_info["ip"], ip_info) for ip_info in domaindata["ips"]]:
try:
if not key in net:
continue
@ -313,34 +315,32 @@ def process_ip_nodes(app, doctree, fromdocname):
tgroup += nodes.colspec(colwidth=colwidth)
thead = nodes.thead()
tgroup += thead
thead += create_table_row([
nodes.paragraph(text=label) for label in header])
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)
]:
for ip, ip_info in [(ip, ips[ip]) for ip in sorted(ips, key=sort_ip)]:
para = nodes.paragraph()
para += nodes.literal('', ip)
para += nodes.literal("", ip)
refnode = nodes.paragraph()
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)
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)
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:
newnode["refuri"] = app.builder.get_relative_uri(
fromdocname, item["docname"]
)
if newnode["refuri"] in refuris:
continue
refuris.add(newnode['refuri'])
refuris.add(newnode["refuri"])
except NoUri:
pass
title = env.titles[item['docname']]
title = env.titles[item["docname"]]
innernode = nodes.Text(title.astext())
newnode.append(innernode)
refnodes.append(newnode)
@ -351,13 +351,13 @@ def process_ip_nodes(app, doctree, fromdocname):
tbody += create_table_row([para, refnode])
content.append(table)
else:
para = nodes.paragraph(_('No IP addresses in this range'))
para = nodes.paragraph(_("No IP addresses in this range"))
content.append(para)
node.replace_self(content)
def setup(app):
app.add_domain(IPDomain)
app.connect('doctree-read', process_ips)
app.connect('doctree-resolved', process_ip_nodes)
return {'version': __version__}
app.connect("doctree-read", process_ips)
app.connect("doctree-resolved", process_ip_nodes)
return {"version": __version__}

View file

@ -1,16 +1,16 @@
#!/usr/bin/env python3
from setuptools import setup, find_packages
from setuptools import find_packages, setup
version = '0.3.1'
version = "0.3.1"
with open('README.rst') as readme:
with open("README.rst") as readme:
description = readme.read() + "\n\n"
with open('CHANGES.rst') as changes:
with open("CHANGES.rst") as changes:
description += changes.read()
requires = ['Sphinx>=3', 'ipcalc>=1.99']
requires = ["Sphinx>=3", "ipcalc>=1.99"]
setup(
@ -24,9 +24,9 @@ setup(
license="GPLv3+",
url="https://pypi.python.org/pypi/jandd.sphinxext.ip",
name="jandd.sphinxext.ip",
namespace_packages=['jandd', 'jandd.sphinxext'],
namespace_packages=["jandd", "jandd.sphinxext"],
packages=find_packages(),
platforms='any',
platforms="any",
version=version,
zip_safe=False,
classifiers=[

View file

@ -13,51 +13,51 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
#import sys
#import os
# import sys
# import os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('..'))
# sys.path.insert(0, os.path.abspath('..'))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ['jandd.sphinxext.ip']
extensions = ["jandd.sphinxext.ip"]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
templates_path = ["_templates"]
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
source_suffix = ".rst"
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
master_doc = "index"
# General information about the project.
project = 'Sphinxext IP Tests'
copyright = '2016, Jan Dittberner'
author = 'Jan Dittberner'
project = "Sphinxext IP Tests"
copyright = "2016, Jan Dittberner"
author = "Jan Dittberner"
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '0.1.0'
version = "0.1.0"
# The full version, including alpha/beta/rc tags.
release = '0.1.0'
release = "0.1.0"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@ -68,38 +68,38 @@ language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
# The reST default role (used for this markup: `text`) to use for all
# documents.
#default_role = None
# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
pygments_style = "sphinx"
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False
# keep_warnings = False
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
@ -109,145 +109,147 @@ todo_include_todos = False
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'alabaster'
html_theme = "alabaster"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# html_theme_path = []
# The name for this set of Sphinx documents.
# "<project> v<release> documentation" by default.
#html_title = 'Sphinxext IP Tests v0.1.0'
# html_title = 'Sphinxext IP Tests v0.1.0'
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# html_logo = None
# The name of an image file (relative to this directory) to use as a favicon of
# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_static_path = ["_static"]
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []
# html_extra_path = []
# If not None, a 'Last updated on:' timestamp is inserted at every page
# bottom, using the given strftime format.
# The empty string is equivalent to '%b %d, %Y'.
#html_last_updated_fmt = None
# html_last_updated_fmt = None
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# html_file_suffix = None
# Language to be used for generating the HTML full-text search index.
# Sphinx supports the following languages:
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja'
# 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr', 'zh'
#html_search_language = 'en'
# html_search_language = 'en'
# A dictionary with options for the search language support, empty by default.
# 'ja' uses this config value.
# 'zh' user can custom change `jieba` dictionary path.
#html_search_options = {'type': 'default'}
# html_search_options = {'type': 'default'}
# The name of a javascript file (relative to the configuration directory) that
# implements a search results scorer. If empty, the default will be used.
#html_search_scorer = 'scorer.js'
# html_search_scorer = 'scorer.js'
# Output file base name for HTML help builder.
htmlhelp_basename = 'SphinxextIPTestsdoc'
htmlhelp_basename = "SphinxextIPTestsdoc"
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
# Latex figure (float) alignment
#'figure_align': 'htbp',
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
# Latex figure (float) alignment
#'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'SphinxextIPTests.tex', 'Sphinxext IP Tests Documentation',
'Jan Dittberner', 'manual'),
(
master_doc,
"SphinxextIPTests.tex",
"Sphinxext IP Tests Documentation",
"Jan Dittberner",
"manual",
),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
@ -255,12 +257,11 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'sphinxextiptests', 'Sphinxext IP Tests Documentation',
[author], 1)
(master_doc, "sphinxextiptests", "Sphinxext IP Tests Documentation", [author], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
@ -269,19 +270,25 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'SphinxextIPTests', 'Sphinxext IP Tests Documentation',
author, 'SphinxextIPTests', 'One line description of project.',
'Miscellaneous'),
(
master_doc,
"SphinxextIPTests",
"Sphinxext IP Tests Documentation",
author,
"SphinxextIPTests",
"One line description of project.",
"Miscellaneous",
),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
# texinfo_no_detailmenu = False

View file

@ -11,23 +11,25 @@ This script runs the jandd.sphinxext.ip unit test suite.
"""
import sys
from os import path
import unittest
from os import path
def run(extra_args=[]):
sys.path.insert(0, path.join(path.dirname(__file__), path.pardir))
sys.path.insert(1, path.abspath(
path.join(path.dirname(__file__), path.pardir,
'jandd', 'sphinxext', 'ip'
))
sys.path.insert(
1,
path.abspath(
path.join(path.dirname(__file__), path.pardir, "jandd", "sphinxext", "ip")
),
)
try:
import sphinx
except ImportError:
print("The sphinx package is needed to run the jandd.sphinxext.ip "
"test suite.")
print(
"The sphinx package is needed to run the jandd.sphinxext.ip " "test suite."
)
from .test_ip import TestIPExtension
@ -37,5 +39,5 @@ def run(extra_args=[]):
unittest.TextTestRunner(verbosity=2).run(suite)
if __name__ == '__main__':
if __name__ == "__main__":
run()

View file

@ -1,40 +1,41 @@
# -*- coding: utf-8 -*-
from io import StringIO
from .util import SphinxTestApplication, test_root
import unittest
from io import StringIO
from .util import SphinxTestApplication, test_root
IP4_ADDRESSES = ['127.0.0.1', '192.168.0.1']
IP6_ADDRESSES = ['::1', '2001:dead:beef::1']
IP4_RANGES = ['172.16.0.0/24', '192.168.0.0/24']
IP6_RANGES = ['2001:dead:beef::/64', '2001:dada:b001::/64']
IP4_ADDRESSES = ["127.0.0.1", "192.168.0.1"]
IP6_ADDRESSES = ["::1", "2001:dead:beef::1"]
IP4_RANGES = ["172.16.0.0/24", "192.168.0.0/24"]
IP6_RANGES = ["2001:dead:beef::/64", "2001:dada:b001::/64"]
class TestIPExtension(unittest.TestCase):
def setUp(self):
if not (test_root / '_static').exists():
(test_root / '_static').mkdir()
if not (test_root / "_static").exists():
(test_root / "_static").mkdir()
self.feed_warnfile = StringIO()
self.app = SphinxTestApplication(
buildername='html', warning=self.feed_warnfile, cleanenv=True)
buildername="html", warning=self.feed_warnfile, cleanenv=True
)
self.app.build(force_all=True, filenames=[])
def tearDown(self):
self.app.cleanup()
(test_root / '_build').rmtree(True)
(test_root / "_build").rmtree(True)
def test_ip_domaindata(self):
self.assertIn('ip', self.app.env.domaindata)
ipdomdata = self.app.env.domaindata['ip']
self.assertIn('v4', ipdomdata)
self.assertIn('v6', ipdomdata)
self.assertIn('v4range', ipdomdata)
self.assertIn('v6range', ipdomdata)
self.assertIn('ips', ipdomdata)
self.assertIn("ip", self.app.env.domaindata)
ipdomdata = self.app.env.domaindata["ip"]
self.assertIn("v4", ipdomdata)
self.assertIn("v6", ipdomdata)
self.assertIn("v4range", ipdomdata)
self.assertIn("v6range", ipdomdata)
self.assertIn("ips", ipdomdata)
def find_in_index(self, entry):
indexentries = self.app.env.get_domain('index').entries
indexentries = self.app.env.get_domain("index").entries
for index in indexentries:
for value in indexentries[index]:
if value[1] == entry:
@ -42,19 +43,19 @@ class TestIPExtension(unittest.TestCase):
self.fail("%s not found in index" % entry)
def test_ip4_addresses(self):
ipv4 = self.app.env.domaindata['ip']['v4']
ips = self.app.env.domaindata['ip']['ips']
ipv4 = self.app.env.domaindata["ip"]["v4"]
ips = self.app.env.domaindata["ip"]["ips"]
for ip in IP4_ADDRESSES:
self.assertIn(ip, ipv4)
self.assertIn(ip, [item['ip'] for item in ips])
self.assertIn(ip, [item["ip"] for item in ips])
self.find_in_index("IPv4 address; %s" % ip)
self.find_in_index("%s; Test page 2" % ip)
def test_ip6_addresses(self):
ipv6 = self.app.env.domaindata['ip']['v6']
ips = self.app.env.domaindata['ip']['ips']
ipv6 = self.app.env.domaindata["ip"]["v6"]
ips = self.app.env.domaindata["ip"]["ips"]
for ip in IP6_ADDRESSES:
self.assertIn(ip, ipv6)
self.assertIn(ip, [item['ip'] for item in ips])
self.assertIn(ip, [item["ip"] for item in ips])
self.find_in_index("IPv6 address; %s" % ip)
self.find_in_index("%s; Test page 2" % ip)

View file

@ -17,15 +17,22 @@ from path import Path
from sphinx import application
__all__ = [
'test_root',
'raises', 'raises_msg', 'Struct',
'ListOutput', 'SphinxTestApplication', 'with_app', 'gen_with_app',
'Path', 'with_tempdir', 'write_file',
'sprint',
"test_root",
"raises",
"raises_msg",
"Struct",
"ListOutput",
"SphinxTestApplication",
"with_app",
"gen_with_app",
"Path",
"with_tempdir",
"write_file",
"sprint",
]
test_root = Path(__file__).parent.joinpath('root').abspath()
test_root = Path(__file__).parent.joinpath("root").abspath()
def _excstr(exc):
@ -44,8 +51,7 @@ def raises(exc, func, *args, **kwds):
except exc:
pass
else:
raise AssertionError('%s did not raise %s' %
(func.__name__, _excstr(exc)))
raise AssertionError("%s did not raise %s" % (func.__name__, _excstr(exc)))
def raises_msg(exc, msg, func, *args, **kwds):
@ -56,10 +62,9 @@ def raises_msg(exc, msg, func, *args, **kwds):
try:
func(*args, **kwds)
except exc as err:
assert msg in str(err), "\"%s\" not in \"%s\"" % (msg, err)
assert msg in str(err), '"%s" not in "%s"' % (msg, err)
else:
raise AssertionError('%s did not raise %s' %
(func.__name__, _excstr(exc)))
raise AssertionError("%s did not raise %s" % (func.__name__, _excstr(exc)))
class Struct(object):
@ -71,6 +76,7 @@ class ListOutput(object):
"""
File-like object that collects written text in a list.
"""
def __init__(self, name):
self.name = name
self.content = []
@ -88,27 +94,38 @@ class SphinxTestApplication(application.Sphinx):
better default values for the initialization parameters.
"""
def __init__(self, srcdir=None, confdir=None, outdir=None, doctreedir=None,
buildername='html', confoverrides=None,
status=None, warning=None, freshenv=None,
warningiserror=None, tags=None,
confname='conf.py', cleanenv=False):
def __init__(
self,
srcdir=None,
confdir=None,
outdir=None,
doctreedir=None,
buildername="html",
confoverrides=None,
status=None,
warning=None,
freshenv=None,
warningiserror=None,
tags=None,
confname="conf.py",
cleanenv=False,
):
application.CONFIG_FILENAME = confname
self.cleanup_trees = [test_root / 'generated']
self.cleanup_trees = [test_root / "generated"]
if srcdir is None:
srcdir = test_root
if srcdir == '(temp)':
if srcdir == "(temp)":
tempdir = Path(tempfile.mkdtemp())
self.cleanup_trees.append(tempdir)
temproot = tempdir / 'root'
temproot = tempdir / "root"
test_root.copytree(temproot)
srcdir = temproot
else:
srcdir = Path(srcdir)
self.builddir = srcdir.joinpath('_build')
self.builddir = srcdir.joinpath("_build")
if confdir is None:
confdir = srcdir
if outdir is None:
@ -117,7 +134,7 @@ class SphinxTestApplication(application.Sphinx):
outdir.makedirs()
self.cleanup_trees.insert(0, outdir)
if doctreedir is None:
doctreedir = srcdir.joinpath(srcdir, self.builddir, 'doctrees')
doctreedir = srcdir.joinpath(srcdir, self.builddir, "doctrees")
if cleanenv:
self.cleanup_trees.insert(0, doctreedir)
if confoverrides is None:
@ -125,15 +142,26 @@ class SphinxTestApplication(application.Sphinx):
if status is None:
status = io.StringIO()
if warning is None:
warning = ListOutput('stderr')
warning = ListOutput("stderr")
if freshenv is None:
freshenv = False
if warningiserror is None:
warningiserror = False
application.Sphinx.__init__(self, srcdir, confdir, outdir, doctreedir,
buildername, confoverrides, status, warning,
freshenv, warningiserror, tags)
application.Sphinx.__init__(
self,
srcdir,
confdir,
outdir,
doctreedir,
buildername,
confoverrides,
status,
warning,
freshenv,
warningiserror,
tags,
)
def cleanup(self, doctrees=False):
for tree in self.cleanup_trees:
@ -145,6 +173,7 @@ def with_app(*args, **kwargs):
Make a TestApp with args and kwargs, pass it to the test and clean up
properly.
"""
def generator(func):
@wraps(func)
def deco(*args2, **kwargs2):
@ -152,7 +181,9 @@ def with_app(*args, **kwargs):
func(app, *args2, **kwargs2)
# don't execute cleanup if test failed
app.cleanup()
return deco
return generator
@ -161,6 +192,7 @@ def gen_with_app(*args, **kwargs):
Make a TestApp with args and kwargs, pass it to the test and clean up
properly.
"""
def generator(func):
@wraps(func)
def deco(*args2, **kwargs2):
@ -169,7 +201,9 @@ def gen_with_app(*args, **kwargs):
yield item
# don't execute cleanup if test failed
app.cleanup()
return deco
return generator
@ -178,15 +212,16 @@ def with_tempdir(func):
tempdir = Path(tempfile.mkdtemp())
func(tempdir)
tempdir.rmtree()
new_func.__name__ = func.__name__
return new_func
def write_file(name, contents):
f = open(str(name), 'wb')
f = open(str(name), "wb")
f.write(contents)
f.close()
def sprint(*args):
sys.stderr.write(' '.join(map(str, args)) + '\n')
sys.stderr.write(" ".join(map(str, args)) + "\n")