summaryrefslogtreecommitdiffstats
path: root/contrib/tools/cython/Cython/Compiler/Tests/TestCmdLine.py
diff options
context:
space:
mode:
authornik-bes <[email protected]>2025-05-19 07:20:13 +0300
committernik-bes <[email protected]>2025-05-19 07:36:02 +0300
commit317b7368e24941ff76499f500579fd9b10f6656e (patch)
treeabbcbaea595e7d2e9f23cf59a408b3082fe4340d /contrib/tools/cython/Cython/Compiler/Tests/TestCmdLine.py
parent6b666a52d40308ab9b3532cd8d3008b9f37cfffb (diff)
Update Cython to 3.0.10.
commit_hash:b43c96b868cd36d636192fd2c6024d9f0d2fb6f8
Diffstat (limited to 'contrib/tools/cython/Cython/Compiler/Tests/TestCmdLine.py')
-rw-r--r--contrib/tools/cython/Cython/Compiler/Tests/TestCmdLine.py479
1 files changed, 444 insertions, 35 deletions
diff --git a/contrib/tools/cython/Cython/Compiler/Tests/TestCmdLine.py b/contrib/tools/cython/Cython/Compiler/Tests/TestCmdLine.py
index bd31da00076..290efd1d7fd 100644
--- a/contrib/tools/cython/Cython/Compiler/Tests/TestCmdLine.py
+++ b/contrib/tools/cython/Cython/Compiler/Tests/TestCmdLine.py
@@ -1,8 +1,12 @@
-
+import os
import sys
import re
from unittest import TestCase
try:
+ from unittest.mock import patch, Mock
+except ImportError: # Py2
+ from mock import patch, Mock
+try:
from StringIO import StringIO
except ImportError:
from io import StringIO # doesn't accept 'str' in Py2
@@ -10,38 +14,39 @@ except ImportError:
from .. import Options
from ..CmdLine import parse_command_line
+from .Utils import backup_Options, restore_Options, check_global_options
-def check_global_options(expected_options, white_list=[]):
- """
- returns error message of "" if check Ok
- """
- no_value = object()
- for name, orig_value in expected_options.items():
- if name not in white_list:
- if getattr(Options, name, no_value) != orig_value:
- return "error in option " + name
- return ""
+unpatched_exists = os.path.exists
+def patched_exists(path):
+ # avoid the Cython command raising a file not found error
+ if path in (
+ 'source.pyx',
+ os.path.join('/work/dir', 'source.pyx'),
+ os.path.join('my_working_path', 'source.pyx'),
+ 'file.pyx',
+ 'file1.pyx',
+ 'file2.pyx',
+ 'file3.pyx',
+ 'foo.pyx',
+ 'bar.pyx',
+ ):
+ return True
+ return unpatched_exists(path)
+@patch('os.path.exists', new=Mock(side_effect=patched_exists))
class CmdLineParserTest(TestCase):
def setUp(self):
- backup = {}
- for name, value in vars(Options).items():
- backup[name] = value
- self._options_backup = backup
+ self._options_backup = backup_Options()
def tearDown(self):
- no_value = object()
- for name, orig_value in self._options_backup.items():
- if getattr(Options, name, no_value) != orig_value:
- setattr(Options, name, orig_value)
+ restore_Options(self._options_backup)
def check_default_global_options(self, white_list=[]):
self.assertEqual(check_global_options(self._options_backup, white_list), "")
def check_default_options(self, options, white_list=[]):
- from ..Main import CompilationOptions, default_options
- default_options = CompilationOptions(default_options)
+ default_options = Options.CompilationOptions(Options.default_options)
no_value = object()
for name in default_options.__dict__.keys():
if name not in white_list:
@@ -121,6 +126,397 @@ class CmdLineParserTest(TestCase):
self.assertEqual(Options.annotate_coverage_xml, 'cov.xml')
self.assertTrue(options.gdb_debug)
self.assertEqual(options.output_dir, '/gdb/outdir')
+ self.assertEqual(options.compiler_directives['wraparound'], False)
+
+ def test_embed_before_positional(self):
+ options, sources = parse_command_line([
+ '--embed',
+ 'source.pyx',
+ ])
+ self.assertEqual(sources, ['source.pyx'])
+ self.assertEqual(Options.embed, 'main')
+
+ def test_two_embeds(self):
+ options, sources = parse_command_line([
+ '--embed', '--embed=huhu',
+ 'source.pyx',
+ ])
+ self.assertEqual(sources, ['source.pyx'])
+ self.assertEqual(Options.embed, 'huhu')
+
+ def test_two_embeds2(self):
+ options, sources = parse_command_line([
+ '--embed=huhu', '--embed',
+ 'source.pyx',
+ ])
+ self.assertEqual(sources, ['source.pyx'])
+ self.assertEqual(Options.embed, 'main')
+
+ def test_no_annotate(self):
+ options, sources = parse_command_line([
+ '--embed=huhu', 'source.pyx'
+ ])
+ self.assertFalse(Options.annotate)
+
+ def test_annotate_short(self):
+ options, sources = parse_command_line([
+ '-a',
+ 'source.pyx',
+ ])
+ self.assertEqual(Options.annotate, 'default')
+
+ def test_annotate_long(self):
+ options, sources = parse_command_line([
+ '--annotate',
+ 'source.pyx',
+ ])
+ self.assertEqual(Options.annotate, 'default')
+
+ def test_annotate_fullc(self):
+ options, sources = parse_command_line([
+ '--annotate-fullc',
+ 'source.pyx',
+ ])
+ self.assertEqual(Options.annotate, 'fullc')
+
+ def test_short_w(self):
+ options, sources = parse_command_line([
+ '-w', 'my_working_path',
+ 'source.pyx'
+ ])
+ self.assertEqual(options.working_path, 'my_working_path')
+ self.check_default_global_options()
+ self.check_default_options(options, ['working_path'])
+
+ def test_short_o(self):
+ options, sources = parse_command_line([
+ '-o', 'my_output',
+ 'source.pyx'
+ ])
+ self.assertEqual(options.output_file, 'my_output')
+ self.check_default_global_options()
+ self.check_default_options(options, ['output_file'])
+
+ def test_short_z(self):
+ options, sources = parse_command_line([
+ '-z', 'my_preimport',
+ 'source.pyx'
+ ])
+ self.assertEqual(Options.pre_import, 'my_preimport')
+ self.check_default_global_options(['pre_import'])
+ self.check_default_options(options)
+
+ def test_convert_range(self):
+ options, sources = parse_command_line([
+ '--convert-range',
+ 'source.pyx'
+ ])
+ self.assertEqual(Options.convert_range, True)
+ self.check_default_global_options(['convert_range'])
+ self.check_default_options(options)
+
+ def test_line_directives(self):
+ options, sources = parse_command_line([
+ '--line-directives',
+ 'source.pyx'
+ ])
+ self.assertEqual(options.emit_linenums, True)
+ self.check_default_global_options()
+ self.check_default_options(options, ['emit_linenums'])
+
+ def test_no_c_in_traceback(self):
+ options, sources = parse_command_line([
+ '--no-c-in-traceback',
+ 'source.pyx'
+ ])
+ self.assertEqual(options.c_line_in_traceback, False)
+ self.check_default_global_options()
+ self.check_default_options(options, ['c_line_in_traceback'])
+
+ def test_gdb(self):
+ options, sources = parse_command_line([
+ '--gdb',
+ 'source.pyx'
+ ])
+ self.assertEqual(options.gdb_debug, True)
+ self.assertEqual(options.output_dir, os.curdir)
+ self.check_default_global_options()
+ self.check_default_options(options, ['gdb_debug', 'output_dir'])
+
+ def test_3str(self):
+ options, sources = parse_command_line([
+ '--3str',
+ 'source.pyx'
+ ])
+ self.assertEqual(options.language_level, '3str')
+ self.check_default_global_options()
+ self.check_default_options(options, ['language_level'])
+
+ def test_capi_reexport_cincludes(self):
+ options, sources = parse_command_line([
+ '--capi-reexport-cincludes',
+ 'source.pyx'
+ ])
+ self.assertEqual(options.capi_reexport_cincludes, True)
+ self.check_default_global_options()
+ self.check_default_options(options, ['capi_reexport_cincludes'])
+
+ def test_fast_fail(self):
+ options, sources = parse_command_line([
+ '--fast-fail',
+ 'source.pyx'
+ ])
+ self.assertEqual(Options.fast_fail, True)
+ self.check_default_global_options(['fast_fail'])
+ self.check_default_options(options)
+
+ def test_cimport_from_pyx(self):
+ options, sources = parse_command_line([
+ '--cimport-from-pyx',
+ 'source.pyx'
+ ])
+ self.assertEqual(Options.cimport_from_pyx, True)
+ self.check_default_global_options(['cimport_from_pyx'])
+ self.check_default_options(options)
+
+ def test_Werror(self):
+ options, sources = parse_command_line([
+ '-Werror',
+ 'source.pyx'
+ ])
+ self.assertEqual(Options.warning_errors, True)
+ self.check_default_global_options(['warning_errors'])
+ self.check_default_options(options)
+
+ def test_warning_errors(self):
+ options, sources = parse_command_line([
+ '--warning-errors',
+ 'source.pyx'
+ ])
+ self.assertEqual(Options.warning_errors, True)
+ self.check_default_global_options(['warning_errors'])
+ self.check_default_options(options)
+
+ def test_Wextra(self):
+ options, sources = parse_command_line([
+ '-Wextra',
+ 'source.pyx'
+ ])
+ self.assertEqual(options.compiler_directives, Options.extra_warnings)
+ self.check_default_global_options()
+ self.check_default_options(options, ['compiler_directives'])
+
+ def test_warning_extra(self):
+ options, sources = parse_command_line([
+ '--warning-extra',
+ 'source.pyx'
+ ])
+ self.assertEqual(options.compiler_directives, Options.extra_warnings)
+ self.check_default_global_options()
+ self.check_default_options(options, ['compiler_directives'])
+
+ def test_old_style_globals(self):
+ options, sources = parse_command_line([
+ '--old-style-globals',
+ 'source.pyx'
+ ])
+ self.assertEqual(Options.old_style_globals, True)
+ self.check_default_global_options(['old_style_globals'])
+ self.check_default_options(options)
+
+ def test_directive_multiple(self):
+ options, source = parse_command_line([
+ '-X', 'cdivision=True',
+ '-X', 'c_string_type=bytes',
+ 'source.pyx'
+ ])
+ self.assertEqual(options.compiler_directives['cdivision'], True)
+ self.assertEqual(options.compiler_directives['c_string_type'], 'bytes')
+ self.check_default_global_options()
+ self.check_default_options(options, ['compiler_directives'])
+
+ def test_directive_multiple_v2(self):
+ options, source = parse_command_line([
+ '-X', 'cdivision=True,c_string_type=bytes',
+ 'source.pyx'
+ ])
+ self.assertEqual(options.compiler_directives['cdivision'], True)
+ self.assertEqual(options.compiler_directives['c_string_type'], 'bytes')
+ self.check_default_global_options()
+ self.check_default_options(options, ['compiler_directives'])
+
+ def test_directive_value_yes(self):
+ options, source = parse_command_line([
+ '-X', 'cdivision=YeS',
+ 'source.pyx'
+ ])
+ self.assertEqual(options.compiler_directives['cdivision'], True)
+ self.check_default_global_options()
+ self.check_default_options(options, ['compiler_directives'])
+
+ def test_directive_value_no(self):
+ options, source = parse_command_line([
+ '-X', 'cdivision=no',
+ 'source.pyx'
+ ])
+ self.assertEqual(options.compiler_directives['cdivision'], False)
+ self.check_default_global_options()
+ self.check_default_options(options, ['compiler_directives'])
+
+ def test_directive_value_invalid(self):
+ self.assertRaises(ValueError, parse_command_line, [
+ '-X', 'cdivision=sadfasd',
+ 'source.pyx'
+ ])
+
+ def test_directive_key_invalid(self):
+ self.assertRaises(ValueError, parse_command_line, [
+ '-X', 'abracadabra',
+ 'source.pyx'
+ ])
+
+ def test_directive_no_value(self):
+ self.assertRaises(ValueError, parse_command_line, [
+ '-X', 'cdivision',
+ 'source.pyx'
+ ])
+
+ def test_compile_time_env_short(self):
+ options, source = parse_command_line([
+ '-E', 'MYSIZE=10',
+ 'source.pyx'
+ ])
+ self.assertEqual(options.compile_time_env['MYSIZE'], 10)
+ self.check_default_global_options()
+ self.check_default_options(options, ['compile_time_env'])
+
+ def test_compile_time_env_long(self):
+ options, source = parse_command_line([
+ '--compile-time-env', 'MYSIZE=10',
+ 'source.pyx'
+ ])
+ self.assertEqual(options.compile_time_env['MYSIZE'], 10)
+ self.check_default_global_options()
+ self.check_default_options(options, ['compile_time_env'])
+
+ def test_compile_time_env_multiple(self):
+ options, source = parse_command_line([
+ '-E', 'MYSIZE=10', '-E', 'ARRSIZE=11',
+ 'source.pyx'
+ ])
+ self.assertEqual(options.compile_time_env['MYSIZE'], 10)
+ self.assertEqual(options.compile_time_env['ARRSIZE'], 11)
+ self.check_default_global_options()
+ self.check_default_options(options, ['compile_time_env'])
+
+ def test_compile_time_env_multiple_v2(self):
+ options, source = parse_command_line([
+ '-E', 'MYSIZE=10,ARRSIZE=11',
+ 'source.pyx'
+ ])
+ self.assertEqual(options.compile_time_env['MYSIZE'], 10)
+ self.assertEqual(options.compile_time_env['ARRSIZE'], 11)
+ self.check_default_global_options()
+ self.check_default_options(options, ['compile_time_env'])
+
+ def test_option_first(self):
+ options, sources = parse_command_line(['-V', 'file.pyx'])
+ self.assertEqual(sources, ['file.pyx'])
+
+ def test_file_inbetween(self):
+ options, sources = parse_command_line(['-V', 'file.pyx', '-a'])
+ self.assertEqual(sources, ['file.pyx'])
+
+ def test_option_trailing(self):
+ options, sources = parse_command_line(['file.pyx', '-V'])
+ self.assertEqual(sources, ['file.pyx'])
+
+ def test_multiple_files(self):
+ options, sources = parse_command_line([
+ 'file1.pyx', '-V',
+ 'file2.pyx', '-a',
+ 'file3.pyx'
+ ])
+ self.assertEqual(sources, ['file1.pyx', 'file2.pyx', 'file3.pyx'])
+
+ def test_debug_flags(self):
+ options, sources = parse_command_line([
+ '--debug-disposal-code', '--debug-coercion',
+ 'file3.pyx'
+ ])
+ from Cython.Compiler import DebugFlags
+ for name in ['debug_disposal_code', 'debug_temp_alloc', 'debug_coercion']:
+ self.assertEqual(getattr(DebugFlags, name), name in ['debug_disposal_code', 'debug_coercion'])
+ setattr(DebugFlags, name, 0) # restore original value
+
+ def test_gdb_overwrites_gdb_outdir(self):
+ options, sources = parse_command_line([
+ '--gdb-outdir=my_dir', '--gdb',
+ 'file3.pyx'
+ ])
+ self.assertEqual(options.gdb_debug, True)
+ self.assertEqual(options.output_dir, os.curdir)
+ self.check_default_global_options()
+ self.check_default_options(options, ['gdb_debug', 'output_dir'])
+
+ def test_gdb_first(self):
+ options, sources = parse_command_line([
+ '--gdb', '--gdb-outdir=my_dir',
+ 'file3.pyx'
+ ])
+ self.assertEqual(options.gdb_debug, True)
+ self.assertEqual(options.output_dir, 'my_dir')
+ self.check_default_global_options()
+ self.check_default_options(options, ['gdb_debug', 'output_dir'])
+
+ def test_coverage_overwrites_annotation(self):
+ options, sources = parse_command_line([
+ '--annotate-fullc', '--annotate-coverage=my.xml',
+ 'file3.pyx'
+ ])
+ self.assertEqual(Options.annotate, True)
+ self.assertEqual(Options.annotate_coverage_xml, 'my.xml')
+ self.check_default_global_options(['annotate', 'annotate_coverage_xml'])
+ self.check_default_options(options)
+
+ def test_coverage_first(self):
+ options, sources = parse_command_line([
+ '--annotate-coverage=my.xml', '--annotate-fullc',
+ 'file3.pyx'
+ ])
+ self.assertEqual(Options.annotate, 'fullc')
+ self.assertEqual(Options.annotate_coverage_xml, 'my.xml')
+ self.check_default_global_options(['annotate', 'annotate_coverage_xml'])
+ self.check_default_options(options)
+
+ def test_annotate_first_fullc_second(self):
+ options, sources = parse_command_line([
+ '--annotate', '--annotate-fullc',
+ 'file3.pyx'
+ ])
+ self.assertEqual(Options.annotate, 'fullc')
+ self.check_default_global_options(['annotate'])
+ self.check_default_options(options)
+
+ def test_annotate_fullc_first(self):
+ options, sources = parse_command_line([
+ '--annotate-fullc', '--annotate',
+ 'file3.pyx'
+ ])
+ self.assertEqual(Options.annotate, 'default')
+ self.check_default_global_options(['annotate'])
+ self.check_default_options(options)
+
+ def test_warning_extra_dont_overwrite(self):
+ options, sources = parse_command_line([
+ '-X', 'cdivision=True',
+ '--warning-extra',
+ '-X', 'c_string_type=bytes',
+ 'source.pyx'
+ ])
+ self.assertTrue(len(options.compiler_directives), len(Options.extra_warnings) + 1)
+ self.check_default_global_options()
+ self.check_default_options(options, ['compiler_directives'])
def test_module_name(self):
options, sources = parse_command_line([
@@ -145,25 +541,38 @@ class CmdLineParserTest(TestCase):
self.assertRaises(SystemExit, parse_command_line, list(args))
finally:
sys.stderr = old_stderr
- msg = stderr.getvalue().strip()
- self.assertTrue(msg)
+ msg = stderr.getvalue()
+ err_msg = 'Message "{}"'.format(msg.strip())
+ self.assertTrue(msg.startswith('usage: '),
+ '%s does not start with "usage :"' % err_msg)
+ self.assertTrue(': error: ' in msg,
+ '%s does not contain ": error :"' % err_msg)
if regex:
self.assertTrue(re.search(regex, msg),
- '"%s" does not match search "%s"' %
- (msg, regex))
+ '%s does not match search "%s"' %
+ (err_msg, regex))
error(['-1'],
- 'Unknown compiler flag: -1')
- error(['-I'])
- error(['--version=-a'])
- error(['--version=--annotate=true'])
- error(['--working'])
- error(['--verbose=1'])
- error(['--cleanup'])
+ 'unknown option -1')
+ error(['-I'],
+ 'argument -I/--include-dir: expected one argument')
+ error(['--version=-a'],
+ "argument -V/--version: ignored explicit argument '-a'")
+ error(['--version=--annotate=true'],
+ "argument -V/--version: ignored explicit argument "
+ "'--annotate=true'")
+ error(['--working'],
+ "argument -w/--working: expected one argument")
+ error(['--verbose=1'],
+ "argument -v/--verbose: ignored explicit argument '1'")
+ error(['--cleanup'],
+ "argument --cleanup: expected one argument")
error(['--debug-disposal-code-wrong-name', 'file3.pyx'],
- "Unknown debug flag: debug_disposal_code_wrong_name")
- error(['--module-name', 'foo.pyx'])
- error(['--module-name', 'foo.bar'])
+ "unknown option --debug-disposal-code-wrong-name")
+ error(['--module-name', 'foo.pyx'],
+ "Need at least one source file")
+ error(['--module-name', 'foo.bar'],
+ "Need at least one source file")
error(['--module-name', 'foo.bar', 'foo.pyx', 'bar.pyx'],
"Only one source file allowed when using --module-name")
error(['--module-name', 'foo.bar', '--timestamps', 'foo.pyx'],