from test.support.os_helper import TESTFN, unlink
from textwrap import dedent
from unittest import TestCase
-import contextlib
import inspect
import os.path
import re
)
self.expect_failure(raw, err)
- @staticmethod
- @contextlib.contextmanager
- def _clinic_version(new_version):
- """Helper for test_version_*() tests"""
- _saved = clinic.version
- clinic.version = new_version
- try:
- yield
- finally:
- clinic.version = _saved
-
- def test_version_directive(self):
- dataset = (
- # (clinic version, required version)
- ('3', '2'), # required version < clinic version
- ('3.1', '3.0'), # required version < clinic version
- ('1.2b0', '1.2a7'), # required version < clinic version
- ('5', '5'), # required version == clinic version
- ('6.1', '6.1'), # required version == clinic version
- ('1.2b3', '1.2b3'), # required version == clinic version
- )
- for clinic_version, required_version in dataset:
- with self.subTest(clinic_version=clinic_version,
- required_version=required_version):
- with self._clinic_version(clinic_version):
- block = dedent(f"""
- /*[clinic input]
- version {required_version}
- [clinic start generated code]*/
- """)
- self.clinic.parse(block)
-
- def test_version_directive_insufficient_version(self):
- with self._clinic_version('4'):
- err = (
- "Insufficient Clinic version!\n"
- " Version: 4\n"
- " Required: 5"
- )
- block = """
- /*[clinic input]
- version 5
- [clinic start generated code]*/
- """
- self.expect_failure(block, err)
-
- def test_version_directive_illegal_char(self):
- err = "Illegal character 'v' in version string 'v5'"
- block = """
- /*[clinic input]
- version v5
- [clinic start generated code]*/
- """
- self.expect_failure(block, err)
-
- def test_version_directive_unsupported_string(self):
- err = "Unsupported version string: '.-'"
- block = """
- /*[clinic input]
- version .-
- [clinic start generated code]*/
- """
- self.expect_failure(block, err)
-
def test_clone_mismatch(self):
err = "'kind' of function and cloned function don't match!"
block = """
# and keyword-only
#
-version = '1'
-
NO_VARARG = "PY_SSIZE_T_MAX"
CLINIC_PREFIX = "__clinic_"
CLINIC_PREFIXED_ARGS = {
return ", ".join(items[:-1]) + " and " + items[-1]
-def version_splitter(s: str) -> tuple[int, ...]:
- """Splits a version string into a tuple of integers.
-
- The following ASCII characters are allowed, and employ
- the following conversions:
- a -> -3
- b -> -2
- c -> -1
- (This permits Python-style version strings such as "1.4b3".)
- """
- version: list[int] = []
- accumulator: list[str] = []
- def flush() -> None:
- if not accumulator:
- fail(f'Unsupported version string: {s!r}')
- version.append(int(''.join(accumulator)))
- accumulator.clear()
-
- for c in s:
- if c.isdigit():
- accumulator.append(c)
- elif c == '.':
- flush()
- elif c in 'abc':
- flush()
- version.append('abc'.index(c) - 3)
- else:
- fail(f'Illegal character {c!r} in version string {s!r}')
- flush()
- return tuple(version)
-
-def version_comparator(version1: str, version2: str) -> Literal[-1, 0, 1]:
- iterator = itertools.zip_longest(
- version_splitter(version1), version_splitter(version2), fillvalue=0
- )
- for a, b in iterator:
- if a < b:
- return -1
- if a > b:
- return 1
- return 0
-
-
class CRenderData:
def __init__(self) -> None:
self.critical_section = False
self.target_critical_section = []
- def directive_version(self, required: str) -> None:
- global version
- if version_comparator(version, required) < 0:
- fail("Insufficient Clinic version!\n"
- f" Version: {version}\n"
- f" Required: {required}")
-
def directive_module(self, name: str) -> None:
fields = name.split('.')[:-1]
module, cls = self.clinic._module_and_class(fields)