env.use_utility_code(pyunicode_equals_utility_code)
self.special_bool_cmp_function = "__Pyx_PyUnicode_Equals"
return True
+ elif type1 is Builtin.bytes_type or type2 is Builtin.bytes_type:
+ env.use_utility_code(pybytes_equals_utility_code)
+ self.special_bool_cmp_function = "__Pyx_PyBytes_Equals"
+ return True
+ elif type1 is Builtin.str_type or type2 is Builtin.str_type:
+ env.use_utility_code(pystr_equals_utility_code)
+ self.special_bool_cmp_function = "__Pyx_PyString_Equals"
+ return True
return False
def generate_operation_code(self, code, result_code,
return -1;
return (equals == Py_EQ) ? (result == 0) : (result != 0);
}
- } else if ((s1 == Py_None) & (s2 == Py_None)) {
- return (equals == Py_EQ);
} else if ((s1 == Py_None) & PyUnicode_CheckExact(s2)) {
return (equals == Py_NE);
} else if ((s2 == Py_None) & PyUnicode_CheckExact(s1)) {
}
""")
+pybytes_equals_utility_code = UtilityCode(
+proto="""
+static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int equals); /*proto*/
+""",
+impl="""
+static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int equals) {
+ if (s1 == s2) { /* as done by PyObject_RichCompareBool(); also catches the (interned) empty string */
+ return (equals == Py_EQ);
+ } else if (PyBytes_CheckExact(s1) & PyBytes_CheckExact(s2)) {
+ if (PyBytes_GET_SIZE(s1) != PyBytes_GET_SIZE(s2)) {
+ return (equals == Py_NE);
+ } else if (PyBytes_GET_SIZE(s1) == 1) {
+ if (equals == Py_EQ)
+ return (PyBytes_AS_STRING(s1)[0] == PyBytes_AS_STRING(s2)[0]);
+ else
+ return (PyBytes_AS_STRING(s1)[0] != PyBytes_AS_STRING(s2)[0]);
+ } else {
+ int result = memcmp(PyBytes_AS_STRING(s1), PyBytes_AS_STRING(s2), PyBytes_GET_SIZE(s1));
+ return (equals == Py_EQ) ? (result == 0) : (result != 0);
+ }
+ } else if ((s1 == Py_None) & PyBytes_CheckExact(s2)) {
+ return (equals == Py_NE);
+ } else if ((s2 == Py_None) & PyBytes_CheckExact(s1)) {
+ return (equals == Py_NE);
+ } else {
+ int result;
+ PyObject* py_result = PyObject_RichCompare(s1, s2, equals);
+ if (!py_result)
+ return -1;
+ result = __Pyx_PyObject_IsTrue(py_result);
+ Py_DECREF(py_result);
+ return result;
+ }
+}
+""",
+requires=[Builtin.include_string_h_utility_code])
+
+pystr_equals_utility_code = UtilityCode(
+proto="""
+#if PY_MAJOR_VERSION >= 3
+#define __Pyx_PyString_Equals __Pyx_PyUnicode_Equals
+#else
+#define __Pyx_PyString_Equals __Pyx_PyBytes_Equals
+#endif
+""",
+requires=[pybytes_equals_utility_code, pyunicode_equals_utility_code])
+
class PrimaryCmpNode(ExprNode, CmpNode):
# Non-cascaded comparison or first comparison of
distutils_distro.parse_config_files(cfgfiles)
EXT_DEP_MODULES = {
- 'numpy' : 'tag:numpy',
- 'pstats' : 'tag:pstats',
- 'posix' : 'tag:posix',
+ 'tag:numpy' : 'numpy',
+ 'tag:pstats': 'pstats',
+ 'tag:posix' : 'posix',
}
-def get_numpy_include_dirs():
+def update_numpy_extension(ext):
import numpy
- return [numpy.get_include()]
+ ext.include_dirs.append(numpy.get_include())
-# TODO: use tags
-EXT_DEP_INCLUDES = [
- # test name matcher , callable returning list
- (re.compile('numpy_.*').match, get_numpy_include_dirs),
-]
+EXT_EXTRAS = {
+ 'tag:numpy' : update_numpy_extension,
+}
# TODO: use tags
VER_DEP_MODULES = {
parse_tags = memoize(parse_tags)
+list_unchanging_dir = memoize(lambda x: os.listdir(x))
+
class build_ext(_build_ext):
def build_extension(self, ext):
os.makedirs(workdir)
suite = unittest.TestSuite()
- filenames = os.listdir(path)
+ filenames = list_unchanging_dir(path)
filenames.sort()
for filename in filenames:
filepath = os.path.join(path, filename)
return suite
def build_tests(self, test_class, path, workdir, module, expect_errors, tags):
- if 'werror' in tags['tags']:
+ if 'werror' in tags['tag']:
warning_errors = True
else:
warning_errors = False
def build_target_filename(self, module_name):
target = '%s.%s' % (module_name, self.language)
return target
-
- def copy_related_files(self, test_directory, target_directory, module_name):
+
+ def related_files(self, test_directory, module_name):
is_related = re.compile('%s_.*[.].*' % module_name).match
- for filename in os.listdir(test_directory):
- if is_related(filename):
- shutil.copy(os.path.join(test_directory, filename),
- target_directory)
+ return [filename for filename in list_unchanging_dir(test_directory)
+ if is_related(filename)]
+
+ def copy_files(self, test_directory, target_directory, file_list):
+ for filename in file_list:
+ shutil.copy(os.path.join(test_directory, filename),
+ target_directory)
- def find_source_files(self, workdir, module_name):
- is_related = re.compile('%s_.*[.]%s' % (module_name, self.language)).match
- return [self.build_target_filename(module_name)] + [
- filename for filename in os.listdir(workdir)
- if is_related(filename) and os.path.isfile(os.path.join(workdir, filename)) ]
+ def source_files(self, workdir, module_name, file_list):
+ return ([self.build_target_filename(module_name)] +
+ [filename for filename in file_list
+ if not os.path.isfile(os.path.join(workdir, filename))])
def split_source_and_output(self, test_directory, module, workdir):
source_file = self.find_module_source_file(os.path.join(test_directory, module) + '.pyx')
def run_distutils(self, test_directory, module, workdir, incdir,
extra_extension_args=None):
+ original_source = self.find_module_source_file(
+ os.path.join(test_directory, module + '.pyx'))
+ try:
+ tags = parse_tags(original_source)
+ except IOError:
+ tags = {}
cwd = os.getcwd()
os.chdir(workdir)
try:
build_extension.finalize_options()
if COMPILER:
build_extension.compiler = COMPILER
- ext_include_dirs = []
- for match, get_additional_include_dirs in EXT_DEP_INCLUDES:
- if match(module):
- ext_include_dirs += get_additional_include_dirs()
ext_compile_flags = CFLAGS[:]
if build_extension.compiler == 'mingw32':
ext_compile_flags.append('-Wno-format')
if extra_extension_args is None:
extra_extension_args = {}
- self.copy_related_files(test_directory, workdir, module)
+ related_files = self.related_files(test_directory, module)
+ self.copy_files(test_directory, workdir, related_files)
extension = Extension(
module,
- sources = self.find_source_files(workdir, module),
- include_dirs = ext_include_dirs,
+ sources = self.source_files(workdir, module, related_files),
extra_compile_args = ext_compile_flags,
**extra_extension_args
)
+ for matcher, fixer in EXT_EXTRAS.items():
+ if isinstance(matcher, str):
+ del EXT_EXTRAS[matcher]
+ matcher = string_selector(matcher)
+ EXT_EXTRAS[matcher] = fixer
+ if matcher(module, tags):
+ extension = fixer(extension) or extension
if self.language == 'cpp':
extension.language = 'c++'
build_extension.extensions = [extension]
class MissingDependencyExcluder:
def __init__(self, deps):
- # deps: { module name : matcher func }
+ # deps: { matcher func : module name }
self.exclude_matchers = []
- for mod, matcher in deps.items():
+ for matcher, mod in deps.items():
try:
__import__(mod)
except ImportError:
parser.add_option("--coverage-xml", dest="coverage_xml",
action="store_true", default=False,
help="collect source coverage data for the Compiler in XML format")
+ parser.add_option("--coverage-html", dest="coverage_html",
+ action="store_true", default=False,
+ help="collect source coverage data for the Compiler in HTML format")
parser.add_option("-A", "--annotate", dest="annotate_source",
action="store_true", default=True,
help="generate annotated HTML versions of the test source files")
WITH_CYTHON = options.with_cython
- if options.coverage or options.coverage_xml:
+ if options.coverage or options.coverage_xml or options.coverage_html:
if not WITH_CYTHON:
- options.coverage = options.coverage_xml = False
+ options.coverage = options.coverage_xml = options.coverage_html = False
else:
from coverage import coverage as _coverage
coverage = _coverage(branch=True)
result = test_runner.run(test_suite)
- if options.coverage or options.coverage_xml:
+ if options.coverage or options.coverage_xml or options.coverage_html:
coverage.stop()
ignored_modules = ('Options', 'Version', 'DebugFlags', 'CmdLine')
modules = [ module for name, module in sys.modules.items()
coverage.report(modules, show_missing=0)
if options.coverage_xml:
coverage.xml_report(modules, outfile="coverage-report.xml")
+ if options.coverage_html:
+ coverage.html_report(modules, directory="coverage-report-html")
if missing_dep_excluder.tests_missing_deps:
sys.stderr.write("Following tests excluded because of missing dependencies on your system:\n")