Added pyversion option for doctest (issue 3303)

This commit is contained in:
Marco Buttu 2017-01-14 18:57:19 +01:00
parent 160b9a5fd0
commit 19298dec33
2 changed files with 53 additions and 24 deletions

View File

@ -20,12 +20,11 @@ from os import path
import doctest
from six import itervalues, StringIO, binary_type, text_type, PY2
from distutils.version import StrictVersion
from docutils import nodes
from docutils.parsers.rst import Directive, directives
from distutils.version import StrictVersion as V
import sphinx
from sphinx.builders import Builder
from sphinx.util import force_decode, logging
@ -107,8 +106,8 @@ class TestDirective(Directive):
if (option[0] not in '+-' or option[1:] not in
doctest.OPTIONFLAGS_BY_NAME): # type: ignore
self.state.document.reporter.warning(
"missing '+' or '-' in '%s' option." % option,
line=self.lineno)
"missing '+' or '-' in '%s' option." % option,
line=self.lineno)
continue
flag = doctest.OPTIONFLAGS_BY_NAME[option[1:]] # type: ignore
node['options'][flag] = (option[0] == '+')
@ -116,32 +115,43 @@ class TestDirective(Directive):
try:
option = self.options['pyversion']
option_strings = option.split()
# :pyversion: >= 3.6 --> op='>=', version='3.6'
# :pyversion: >= 3.6 --> operand='>=', version='3.6'
operand, version = [item.strip() for item in option_strings]
operands = ('<=', '<', '==', '>=', '>')
if operand not in operands:
self.state.document.reporter.warning(
"'%s' is not a valid pyversion operand.\n"
"Avaliable operands: %s" % (operand, operands),
line=self.lineno)
else:
rv = V(platform.python_version()) # Running version
sv = V(version) # Specified version
skip = ((operand == '<=' and not (rv <= sv)) or
(operand == '<' and not (rv < sv)) or
(operand == '==' and not (rv == sv)) or
(operand == '>=' and not (rv >= sv)) or
(operand == '>' and not (rv > sv)))
if skip:
flag = doctest.OPTIONFLAGS_BY_NAME['SKIP']
node['options'][flag] = True
if not self.proper_pyversion(operand, version):
flag = doctest.OPTIONFLAGS_BY_NAME['SKIP']
node['options'][flag] = True # Skip the test
except ValueError:
self.state.document.reporter.warning(
"'%s' is not a valid pyversion value" % option,
line=self.lineno)
"'%s' is not a valid pyversion value" % option,
line=self.lineno)
return [node]
def proper_pyversion(self, operand, version):
"""Compare `version` to the Python version, relying on `operand`.
This function is meant to be used to evaluate the doctest :pyversion:
option. For instance, if the doctest directive provides the option
:pyversion: >= 3.3, then we have to check if the running Python version
is greather or equal to 3.3. In that case, operand will be the string
'>=' and version the string '3.3'. proper_pyversion() will return True
if the running Python version is >= 3.3, False otherwise.
"""
operands = ('<=', '<', '==', '>=', '>')
if operand not in operands:
self.document.reporter.warning(
"'%s' is not a valid pyversion operand.\n"
"Avaliable operands: %s" % (operand, operands),
line=self.lineno)
return True # Be defensive, making the doctest to be executed
rv = StrictVersion(platform.python_version()) # Running version
sv = StrictVersion(version) # Specified version
return ((operand == '<=' and (rv <= sv)) or
(operand == '<' and (rv < sv)) or
(operand == '==' and (rv == sv)) or
(operand == '>=' and (rv >= sv)) or
(operand == '>' and (rv > sv)))
class TestsetupDirective(TestDirective):
option_spec = {} # type: Dict

View File

@ -8,7 +8,9 @@
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import platform
import pytest
from sphinx.ext.doctest import TestDirective as _TestDirective
cleanup_called = 0
@ -25,6 +27,23 @@ def test_build(app, status, warning):
assert cleanup_called == 3, 'testcleanup did not get executed enough times'
def test_pyversion(monkeypatch):
def python_version():
return '3.3'
monkeypatch.setattr(platform, 'python_version', python_version)
td = _TestDirective(*([None] * 9))
assert td.proper_pyversion('<', '3.4') is True
assert td.proper_pyversion('<', '3.2') is False
assert td.proper_pyversion('<=', '3.4') is True
assert td.proper_pyversion('<=', '3.3') is True
assert td.proper_pyversion('==', '3.3') is True
assert td.proper_pyversion('>=', '3.4') is False
assert td.proper_pyversion('>=', '3.2') is True
assert td.proper_pyversion('>', '3.4') is False
assert td.proper_pyversion('>', '3.2') is True
assert td.proper_pyversion('>', '3.3a0') is True
def cleanup_call():
global cleanup_called
cleanup_called += 1