Fix compatibility with Sphinx 2.1

- Fix deprecation warnings
- Fix missing API in tests
- Fix relative imports in tests
- use proper logger
This commit is contained in:
Jan Dittberner 2019-07-13 21:52:52 +02:00
parent fc809c1041
commit 585085250e
4 changed files with 48 additions and 37 deletions

View file

@ -18,14 +18,18 @@ from docutils.parsers.rst import Directive
from sphinx import addnodes from sphinx import addnodes
from sphinx.domains import Domain, ObjType from sphinx.domains import Domain, ObjType
from sphinx.environment import NoUri from sphinx.errors import NoUri
from sphinx.locale import l_ from sphinx.locale import _
from sphinx.roles import XRefRole from sphinx.roles import XRefRole
from sphinx.util import logging
from sphinx.util.nodes import make_refnode from sphinx.util.nodes import make_refnode
__version__ = '0.2.5.dev1' __version__ = '0.2.5.dev1'
logger = logging.getLogger(__name__)
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
@ -52,13 +56,17 @@ class IPXRefRole(XRefRole):
super(IPXRefRole, self).__init__( super(IPXRefRole, self).__init__(
innernodeclass=innernodeclass, **kwargs) innernodeclass=innernodeclass, **kwargs)
def __call__(self, typ, rawtext, text, lineno, inliner, def __cal__(self, typ, rawtext, text, lineno, inliner,
options={}, content=[]): options=None, content=None):
if content is None:
content = []
if options is None:
options = {}
try: try:
Network(text) Network(text)
except ValueError as e: except ValueError as e:
env = inliner.document.settings.env env = inliner.document.settings.env
env.warn(env.docname, "invalid ip address/range %s" % text, lineno) logger.warning("invalid ip address/range %s" % text, location=(env.docname, lineno))
return [nodes.literal(text, text), []] return [nodes.literal(text, text), []]
return super(IPXRefRole, self).__call__( return super(IPXRefRole, self).__call__(
typ, rawtext, text, lineno, inliner, options, content) typ, rawtext, text, lineno, inliner, options, content)
@ -140,20 +148,20 @@ class IPv4Range(IPRange):
typ = 'v4range' typ = 'v4range'
def get_prefix_title(self): def get_prefix_title(self):
return l_('IPv4 address range ') return _('IPv4 address range ')
def get_index_text(self): def get_index_text(self):
return "%s; %s" % (l_('IPv4 range'), self.rangespec) return "%s; %s" % (_('IPv4 range'), self.rangespec)
class IPv6Range(IPRange): class IPv6Range(IPRange):
typ = 'v6range' typ = 'v6range'
def get_prefix_title(self): def get_prefix_title(self):
return l_('IPv6 address range ') return _('IPv6 address range ')
def get_index_text(self): def get_index_text(self):
return "%s; %s" % (l_('IPv6 range'), self.rangespec) return "%s; %s" % (_('IPv6 range'), self.rangespec)
class IPDomain(Domain): class IPDomain(Domain):
@ -164,10 +172,10 @@ class IPDomain(Domain):
label = 'IP addresses and ranges.' label = 'IP addresses and ranges.'
object_types = { object_types = {
'v4': ObjType(l_('v4'), 'v4', 'obj'), 'v4': ObjType(_('v4'), 'v4', 'obj'),
'v6': ObjType(l_('v6'), 'v6', 'obj'), 'v6': ObjType(_('v6'), 'v6', 'obj'),
'v4range': ObjType(l_('v4range'), 'v4range', 'obj'), 'v4range': ObjType(_('v4range'), 'v4range', 'obj'),
'v6range': ObjType(l_('v6range'), 'v6range', 'obj'), 'v6range': ObjType(_('v6range'), 'v6range', 'obj'),
} }
directives = { directives = {
@ -176,10 +184,10 @@ class IPDomain(Domain):
} }
roles = { roles = {
'v4': IPXRefRole('v4', l_('IPv4 address')), 'v4': IPXRefRole('v4', _('IPv4 address')),
'v6': IPXRefRole('v6', l_('IPv6 address')), 'v6': IPXRefRole('v6', _('IPv6 address')),
'v4range': IPXRefRole('v4range', l_('IPv4 range')), 'v4range': IPXRefRole('v4range', _('IPv4 range')),
'v6range': IPXRefRole('v6range', l_('IPv6 range')), 'v6range': IPXRefRole('v6range', _('IPv6 range')),
} }
initial_data = { initial_data = {
@ -277,7 +285,7 @@ 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')) header = (_('IP address'), _('Used by'))
colwidths = (1, 3) colwidths = (1, 3)
for node in doctree.traverse(ip_range): for node in doctree.traverse(ip_range):
@ -286,8 +294,14 @@ def process_ip_nodes(app, doctree, fromdocname):
ips = {} ips = {}
for key, value in [ for key, value in [
(ip_info['ip'], ip_info) for ip_info in (ip_info['ip'], ip_info) for ip_info in
domaindata['ips'] if ip_info['ip'] in net domaindata['ips']
]: ]:
try:
if not key in net:
continue
except ValueError as e:
logger.info("invalid IP address info %s", e.args)
continue
addrlist = ips.get(key, []) addrlist = ips.get(key, [])
addrlist.append(value) addrlist.append(value)
ips[key] = addrlist ips[key] = addrlist
@ -337,7 +351,7 @@ def process_ip_nodes(app, doctree, fromdocname):
tbody += create_table_row([para, refnode]) tbody += create_table_row([para, refnode])
content.append(table) content.append(table)
else: else:
para = nodes.paragraph(l_('No IP addresses in this range')) para = nodes.paragraph(_('No IP addresses in this range'))
content.append(para) content.append(para)
node.replace_self(content) node.replace_self(content)

View file

@ -29,13 +29,11 @@ def run(extra_args=[]):
print("The sphinx package is needed to run the jandd.sphinxext.ip " print("The sphinx package is needed to run the jandd.sphinxext.ip "
"test suite.") "test suite.")
import test_ip from .test_ip import TestIPExtension
print("Running jandd.sphinxext.ip test suite ...") print("Running jandd.sphinxext.ip test suite ...")
suite = unittest.TestLoader().loadTestsFromTestCase( suite = unittest.TestLoader().loadTestsFromTestCase(TestIPExtension)
test_ip.TestIPExtension
)
unittest.TextTestRunner(verbosity=2).run(suite) unittest.TextTestRunner(verbosity=2).run(suite)

View file

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from io import StringIO from io import StringIO
from util import TestApp, test_root from .util import TestApp, test_root
import unittest import unittest

View file

@ -7,21 +7,14 @@
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
import sys
import io import io
import tempfile
import shutil import shutil
import sys
try: import tempfile
from functools import wraps from functools import wraps
except ImportError:
# functools is new in 2.4
wraps = lambda f: (lambda w: w)
from sphinx import application
from sphinx.ext.autodoc import AutoDirective
from path import Path from path import Path
from sphinx import application
__all__ = [ __all__ = [
'test_root', 'test_root',
@ -40,6 +33,7 @@ def _excstr(exc):
return str(tuple(map(_excstr, exc))) return str(tuple(map(_excstr, exc)))
return exc.__name__ return exc.__name__
def raises(exc, func, *args, **kwds): def raises(exc, func, *args, **kwds):
""" """
Raise :exc:`AssertionError` if ``func(*args, **kwds)`` does not Raise :exc:`AssertionError` if ``func(*args, **kwds)`` does not
@ -53,6 +47,7 @@ def raises(exc, func, *args, **kwds):
raise AssertionError('%s did not raise %s' % raise AssertionError('%s did not raise %s' %
(func.__name__, _excstr(exc))) (func.__name__, _excstr(exc)))
def raises_msg(exc, msg, func, *args, **kwds): def raises_msg(exc, msg, func, *args, **kwds):
""" """
Raise :exc:`AssertionError` if ``func(*args, **kwds)`` does not Raise :exc:`AssertionError` if ``func(*args, **kwds)`` does not
@ -71,6 +66,7 @@ class Struct(object):
def __init__(self, **kwds): def __init__(self, **kwds):
self.__dict__.update(kwds) self.__dict__.update(kwds)
class ListOutput(object): class ListOutput(object):
""" """
File-like object that collects written text in a list. File-like object that collects written text in a list.
@ -85,6 +81,7 @@ class ListOutput(object):
def write(self, text): def write(self, text):
self.content.append(text) self.content.append(text)
class TestApp(application.Sphinx): class TestApp(application.Sphinx):
""" """
A subclass of :class:`Sphinx` that runs on the test root, with some A subclass of :class:`Sphinx` that runs on the test root, with some
@ -139,7 +136,6 @@ class TestApp(application.Sphinx):
freshenv, warningiserror, tags) freshenv, warningiserror, tags)
def cleanup(self, doctrees=False): def cleanup(self, doctrees=False):
AutoDirective._registry.clear()
for tree in self.cleanup_trees: for tree in self.cleanup_trees:
shutil.rmtree(tree, True) shutil.rmtree(tree, True)
@ -176,6 +172,7 @@ def gen_with_app(*args, **kwargs):
return deco return deco
return generator return generator
def with_tempdir(func): def with_tempdir(func):
def new_func(): def new_func():
tempdir = Path(tempfile.mkdtemp()) tempdir = Path(tempfile.mkdtemp())
@ -184,10 +181,12 @@ def with_tempdir(func):
new_func.__name__ = func.__name__ new_func.__name__ = func.__name__
return new_func return new_func
def write_file(name, contents): def write_file(name, contents):
f = open(str(name), 'wb') f = open(str(name), 'wb')
f.write(contents) f.write(contents)
f.close() f.close()
def sprint(*args): def sprint(*args):
sys.stderr.write(' '.join(map(str, args)) + '\n') sys.stderr.write(' '.join(map(str, args)) + '\n')