Exemple #1
0
def test_push_dir(tmpdir):
    assert os.path.split(os.getcwd())[-1] == 'tests'

    from skbuild.utils import push_dir

    # No directory
    with push_dir():
        os.chdir(os.path.join(os.getcwd(), '..'))
        assert os.path.split(os.getcwd())[-1] == 'scikit-build'
    assert os.path.split(os.getcwd())[-1] == 'tests'

    # With existing directory
    with push_dir(directory=os.path.join(os.getcwd(), '..')):
        assert os.path.split(os.getcwd())[-1] == 'scikit-build'
    assert os.path.split(os.getcwd())[-1] == 'tests'

    foo_directory = os.path.join(str(tmpdir), 'foo')

    # With non existing directory
    failed = False
    try:
        with push_dir(directory=foo_directory):
            pass
    except OSError:
        failed = True
    assert failed
    assert not os.path.isdir(foo_directory)

    # With make_directory option
    with push_dir(directory=foo_directory, make_directory=True):
        assert os.getcwd() == foo_directory
    assert os.path.split(os.getcwd())[-1] == 'tests'
    assert os.path.isdir(foo_directory)
def test_outside_project_root_fails(option):

    with push_dir():

        expected_failure = False

        cmd = ["install"]
        if option is not None:
            expected_failure = True
            cmd.extend(["--", option])

        @project_setup_py_test(("samples", "fail-outside-project-root"),
                               cmd,
                               clear_cache=True)
        def should_fail():
            pass

        failed = False
        msg = ""
        try:
            should_fail()
        except SystemExit as e:
            failed = isinstance(e.code, SKBuildError)
            msg = str(e)
        except SKBuildError as e:
            failed = True
            msg = str(e)

    assert expected_failure == failed

    if expected_failure:
        assert "CMake-installed files must be within the project root." in msg
Exemple #3
0
        def wrapped(*iargs, **ikwargs):

            # Clear distutils.dir_util.mkpath() cache
            # See issue scikit-build#120
            distutils.dir_util._path_created = {}

            dir = list(wrapped.project)
            dir.insert(0, os.path.dirname(os.path.abspath(__file__)))
            dir = os.path.join(*dir)

            with push_dir(dir), push_argv(["setup.py"] + wrapped.setup_args):

                if wrapped.clear_cache:
                    # XXX We assume dist_dir is not customized
                    dest_dir = 'dist'
                    for dir_to_remove in [SKBUILD_DIR, dest_dir]:
                        if os.path.exists(dir_to_remove):
                            shutil.rmtree(dir_to_remove)

                setup_code = None
                with open("setup.py", "r") as fp:
                    setup_code = compile(fp.read(), "setup.py", mode="exec")

                if setup_code is not None:
                    six.exec_(setup_code)

                result2 = fun(*iargs, **ikwargs)

            return result2
def test_invalid_cmake(exception, mocker):

    exceptions = {
        OSError: OSError('Unknown error'),
        CalledProcessError: CalledProcessError(['cmake', '--version'], 1)
    }

    mocker.patch('subprocess.check_call',
                 side_effect=exceptions[exception])

    with push_dir():

        @project_setup_py_test(("samples", "hello"), ["build"],
                               clear_cache=True)
        def should_fail():
            pass

        failed = False
        message = ""
        try:
            should_fail()
        except SystemExit as e:
            failed = isinstance(e.code, SKBuildError)
            message = str(e)

    assert failed
    assert "Problem with the CMake installation, aborting build." in message
Exemple #5
0
def test_hello_builds_with_generator(generator_args):
    with push_dir():

        build_args = ["build"]
        build_args.extend(generator_args)

        @project_setup_py_test(("samples", "hello"), build_args,
                               clear_cache=True)
        def run():
            pass

        failed = False
        message = ""
        try:
            run()
        except SystemExit as e:
            failed = isinstance(e.code, SKBuildError)
            message = str(e)

        if 'invalid' in generator_args:
            assert failed
            assert "Could not get working generator for your system." \
                   "  Aborting build." in message
        else:
            assert not failed
def initialize_git_repo_and_commit(project_dir, verbose=True):
    """Convenience function creating a git repository in ``project_dir``.

    If ``project_dir`` does NOT contain a ``.git`` directory, a new
    git repository with one commit containing all the directories and files
    is created.
    """
    if isinstance(project_dir, six.string_types):
        project_dir = py.path.local(project_dir)

    if project_dir.join('.git').exists():
        return

    # If any, exclude virtualenv files
    project_dir.join(".gitignore").write(".env")

    with push_dir(str(project_dir)):
        for cmd in [
            ['git', 'init'],
            ['git', 'config', 'user.name', 'scikit-build'],
            ['git', 'config', 'user.email', 'test@test'],
            ['git', 'add', '-A'],
            ['git', 'reset', '.gitignore'],
            ['git', 'commit', '-m', 'Initial commit']
        ]:
            do_call = (subprocess.check_call
                       if verbose else subprocess.check_output)
            do_call(cmd)
Exemple #7
0
def test_invalid_generator(mocker, capfd):
    platform = get_platform()
    mocker.patch.object(type(platform),
                        'default_generators',
                        new_callable=mocker.PropertyMock,
                        return_value=[CMakeGenerator('Invalid')])
    mocker.patch('skbuild.cmaker.get_platform', return_value=platform)

    with push_dir(), push_env(CMAKE_GENERATOR=None):

        @project_setup_py_test("hello", ["build"])
        def should_fail():
            pass

        failed = False
        message = ""
        try:
            should_fail()
        except SystemExit as e:
            failed = isinstance(e.code, SKBuildError)
            message = str(e)

    _, err = capfd.readouterr()

    assert "CMake Error: Could not create named generator Invalid" in err
    assert failed
    assert "scikit-build could not get a working generator for your system." \
           " Aborting build." in message
Exemple #8
0
def test_invalid_cmake(exception, mocker):

    exceptions = {
        OSError: OSError('Unknown error'),
        CalledProcessError: CalledProcessError(['cmake', '--version'], 1)
    }

    check_call_original = check_call

    def check_call_mock(*args, **kwargs):
        if args[0] == ['cmake', '--version']:
            raise exceptions[exception]
        check_call_original(*args, **kwargs)

    mocker.patch('skbuild.cmaker.subprocess.check_call', new=check_call_mock)

    with push_dir():

        @project_setup_py_test("hello", ["build"])
        def should_fail():
            pass

        failed = False
        message = ""
        try:
            should_fail()
        except SystemExit as e:
            failed = isinstance(e.code, SKBuildError)
            message = str(e)

    assert failed
    assert "Problem with the CMake installation, aborting build." in message
def test_invalid_cmake(exception, mocker):

    exceptions = {
        OSError: OSError('Unknown error'),
        CalledProcessError: CalledProcessError(['cmake', '--version'], 1)
    }

    check_output_original = check_output

    def check_output_mock(*args, **kwargs):
        if args[0] == ['cmake', '--version']:
            raise exceptions[exception]
        check_output_original(*args, **kwargs)

    mocker.patch('skbuild.cmaker.subprocess.check_output',
                 new=check_output_mock)

    with push_dir():

        @project_setup_py_test("hello-no-language", ["build"], disable_languages_test=True)
        def should_fail():
            pass

        failed = False
        message = ""
        try:
            should_fail()
        except SystemExit as e:
            failed = isinstance(e.code, SKBuildError)
            message = str(e)

    assert failed
    assert "Problem with the CMake installation, aborting build." in message
def test_hello_cleans(capfd):
    with push_dir():

        tmp_dir = _tmpdir("test_hello_cleans")

        _copy_dir(tmp_dir, os.path.join(SAMPLES_DIR, "hello-cpp"))

        @project_setup_py_test("hello-cpp", ["build"], tmp_dir=tmp_dir)
        def run_build():
            pass

        @project_setup_py_test("hello-cpp", ["clean"], tmp_dir=tmp_dir)
        def run_clean():
            pass

        # Check that a project can be cleaned twice in a row
        run_build()
        print("<<-->>")
        run_clean()
        print("<<-->>")
        run_clean()

    _, clean1_out, clean2_out = \
        capfd.readouterr()[0].split('<<-->>')

    clean1_out = clean1_out.strip()
    clean2_out = clean2_out.strip()

    assert "running clean" == clean1_out.splitlines()[0]
    assert "removing '{}'".format(CMAKE_INSTALL_DIR) == clean1_out.splitlines()[1]
    assert "removing '{}'".format(CMAKE_BUILD_DIR) == clean1_out.splitlines()[2]
    assert "removing '{}'".format(SKBUILD_DIR) == clean1_out.splitlines()[3]

    assert "running clean" == clean2_out
def test_invalid_generator(mocker, capfd):
    platform = get_platform()
    mocker.patch.object(type(platform), 'default_generators',
                        new_callable=mocker.PropertyMock,
                        return_value=[CMakeGenerator('Invalid')])
    mocker.patch('skbuild.cmaker.get_platform', return_value=platform)

    with push_dir(), push_env(CMAKE_GENERATOR=None):
        @project_setup_py_test("hello-no-language", ["build"])
        def should_fail():
            pass

        failed = False
        message = ""
        try:
            should_fail()
        except SystemExit as e:
            failed = isinstance(e.code, SKBuildError)
            message = str(e)

    _, err = capfd.readouterr()

    assert "CMake Error: Could not create named generator Invalid" in err
    assert failed
    assert "scikit-build could not get a working generator for your system." \
           " Aborting build." in message
def test_hello_clean(capfd):
    with push_dir():

        skbuild_dir = os.path.join(
            "tests", "samples", "hello-pure", SKBUILD_DIR)

        @project_setup_py_test(("samples", "hello-pure"), ["build"],
                               clear_cache=True)
        def run_build():
            pass

        run_build()

        assert os.path.exists(skbuild_dir)

        @project_setup_py_test(("samples", "hello-pure"), ["clean"])
        def run_clean():
            pass

        run_clean()

        assert not os.path.exists(skbuild_dir)

        out = capfd.readouterr()[0]
        assert 'Build files have been written to' not in out
Exemple #13
0
def test_outside_project_root_fails(option):

    with push_dir():

        expected_failure = False

        cmd = ["install"]
        if option is not None:
            expected_failure = True
            cmd.extend(["--", option])

        @project_setup_py_test("fail-outside-project-root", cmd)
        def should_fail():
            pass

        failed = False
        msg = ""
        try:
            should_fail()
        except SystemExit as e:
            failed = isinstance(e.code, SKBuildError)
            msg = str(e)
        except SKBuildError as e:
            failed = True
            msg = str(e)

    assert expected_failure == failed

    if expected_failure:
        assert "CMake-installed files must be within the project root." in msg
Exemple #14
0
def initialize_git_repo_and_commit(project_dir, verbose=True):
    """Convenience function creating a git repository in ``project_dir``.

    If ``project_dir`` does NOT contain a ``.git`` directory, a new
    git repository with one commit containing all the directories and files
    is created.
    """
    if isinstance(project_dir, six.string_types):
        project_dir = py.path.local(project_dir)

    if project_dir.join('.git').exists():
        return

    # If any, exclude virtualenv files
    project_dir.join(".gitignore").write(".env")

    with push_dir(str(project_dir)):
        for cmd in [['git', 'init'],
                    ['git', 'config', 'user.name', 'scikit-build'],
                    ['git', 'config', 'user.email', 'test@test'],
                    ['git', 'add', '-A'], ['git', 'reset', '.gitignore'],
                    ['git', 'commit', '-m', 'Initial commit']]:
            do_call = (subprocess.check_call
                       if verbose else subprocess.check_output)
            do_call(cmd)
Exemple #15
0
def test_hello_cleans(capfd):
    with push_dir():

        @project_setup_py_test(("samples", "hello"), ["build"],
                               clear_cache=True)
        def run_build():
            pass

        @project_setup_py_test(("samples", "hello"), ["clean"])
        def run_clean():
            pass

        # Check that a project can be cleaned twice in a row
        run_build()
        print("<<-->>")
        run_clean()
        print("<<-->>")
        run_clean()

    _, clean1_out, clean2_out = \
        capfd.readouterr()[0].split('<<-->>')

    clean1_out = clean1_out.strip()
    clean2_out = clean2_out.strip()

    assert "running clean" == clean1_out.splitlines()[0]
    assert "removing '_skbuild{}cmake-install'".format(os.path.sep) \
           == clean1_out.splitlines()[1]
    assert "removing '_skbuild{}cmake-build'".format(os.path.sep) \
           == clean1_out.splitlines()[2]
    assert "removing '_skbuild'" == clean1_out.splitlines()[3]

    assert "running clean" == clean2_out
Exemple #16
0
def test_hello_cleans(capfd):
    with push_dir():

        tmp_dir = _tmpdir("test_hello_cleans")

        _copy_dir(tmp_dir, os.path.join(SAMPLES_DIR, "hello-cpp"))

        @project_setup_py_test("hello-cpp", ["build"], tmp_dir=tmp_dir)
        def run_build():
            pass

        @project_setup_py_test("hello-cpp", ["clean"], tmp_dir=tmp_dir)
        def run_clean():
            pass

        # Check that a project can be cleaned twice in a row
        run_build()
        print("<<-->>")
        run_clean()
        print("<<-->>")
        run_clean()

    _, clean1_out, clean2_out = \
        capfd.readouterr()[0].split('<<-->>')

    clean1_out = clean1_out.strip()
    clean2_out = clean2_out.strip()

    assert "running clean" == clean1_out.splitlines()[0]
    assert "removing '{}'".format(CMAKE_INSTALL_DIR()) == clean1_out.splitlines()[1]
    assert "removing '{}'".format(CMAKE_BUILD_DIR()) == clean1_out.splitlines()[2]
    assert "removing '{}'".format(SKBUILD_DIR()) == clean1_out.splitlines()[3]

    assert "running clean" == clean2_out
Exemple #17
0
def test_make_without_configure_fails(capfd):
    src_dir = _tmpdir('test_make_without_configure_fails')
    src_dir.ensure(CMAKE_BUILD_DIR, dir=1)
    with push_dir(str(src_dir)), pytest.raises(SKBuildError) as excinfo:
        CMaker().make()
    _, err = capfd.readouterr()
    assert "An error occurred while building with CMake." in str(excinfo.value)
    assert "Error: could not load cache" in err
def test_make_without_configure_fails(capfd):
    src_dir = _tmpdir('test_make_without_configure_fails')
    src_dir.ensure(CMAKE_BUILD_DIR, dir=1)
    with push_dir(str(src_dir)), pytest.raises(SKBuildError) as excinfo:
        CMaker().make()
    _, err = capfd.readouterr()
    assert "An error occurred while building with CMake." in str(excinfo.value)
    assert "Error: could not load cache" in err
def test_make(configure_with_cmake_source_dir, capfd):
    tmp_dir = _tmpdir('test_make')
    with push_dir(str(tmp_dir)):

        src_dir = tmp_dir.ensure('SRC', dir=1)
        src_dir.join('CMakeLists.txt').write(textwrap.dedent(
            """
            cmake_minimum_required(VERSION 3.5.0)
            project(foobar NONE)
            file(WRITE "${CMAKE_BINARY_DIR}/foo.txt" "# foo")
            install(FILES "${CMAKE_BINARY_DIR}/foo.txt" DESTINATION ".")
            install(CODE "message(STATUS \\"Project has been installed\\")")
            message(STATUS "CMAKE_SOURCE_DIR:${CMAKE_SOURCE_DIR}")
            message(STATUS "CMAKE_BINARY_DIR:${CMAKE_BINARY_DIR}")
            """
        ))
        src_dir.ensure(CMAKE_BUILD_DIR, dir=1)

        with push_dir(str(src_dir)
                      if not configure_with_cmake_source_dir
                      else str(tmp_dir.ensure('BUILD', dir=1))):
            cmkr = CMaker()
            config_kwargs = {}
            if configure_with_cmake_source_dir:
                config_kwargs['cmake_source_dir'] = str(src_dir)
            env = cmkr.configure(**config_kwargs)
            cmkr.make(env=env)

        messages = ["Project has been installed"]

        if configure_with_cmake_source_dir:
            messages += [
                "/SRC",
                "/BUILD/{}".format(to_unix_path(CMAKE_BUILD_DIR)),
                "/BUILD/{}/./foo.txt".format(to_unix_path(CMAKE_INSTALL_DIR))
            ]
        else:
            messages += [
                "/SRC",
                "/SRC/{}".format(to_unix_path(CMAKE_BUILD_DIR)),
                "/SRC/{}/./foo.txt".format(to_unix_path(CMAKE_INSTALL_DIR)),
            ]

        out, _ = capfd.readouterr()
        for message in messages:
            assert message in out
Exemple #20
0
def test_make(configure_with_cmake_source_dir, capfd):
    tmp_dir = _tmpdir('test_make')
    with push_dir(str(tmp_dir)):

        src_dir = tmp_dir.ensure('SRC', dir=1)
        src_dir.join('CMakeLists.txt').write(textwrap.dedent(
            """
            cmake_minimum_required(VERSION 3.5.0)
            project(foobar NONE)
            file(WRITE "${CMAKE_BINARY_DIR}/foo.txt" "# foo")
            install(FILES "${CMAKE_BINARY_DIR}/foo.txt" DESTINATION ".")
            install(CODE "message(STATUS \\"Project has been installed\\")")
            message(STATUS "CMAKE_SOURCE_DIR:${CMAKE_SOURCE_DIR}")
            message(STATUS "CMAKE_BINARY_DIR:${CMAKE_BINARY_DIR}")
            """
        ))
        src_dir.ensure(CMAKE_BUILD_DIR, dir=1)

        with push_dir(str(src_dir)
                      if not configure_with_cmake_source_dir
                      else str(tmp_dir.ensure('BUILD', dir=1))):
            cmkr = CMaker()
            config_kwargs = {}
            if configure_with_cmake_source_dir:
                config_kwargs['cmake_source_dir'] = str(src_dir)
            env = cmkr.configure(**config_kwargs)
            cmkr.make(env=env)

        messages = ["Project has been installed"]

        if configure_with_cmake_source_dir:
            messages += [
                "/SRC",
                "/BUILD/{}".format(to_unix_path(CMAKE_BUILD_DIR)),
                "/BUILD/{}/./foo.txt".format(to_unix_path(CMAKE_INSTALL_DIR))
            ]
        else:
            messages += [
                "/SRC",
                "/SRC/{}".format(to_unix_path(CMAKE_BUILD_DIR)),
                "/SRC/{}/./foo.txt".format(to_unix_path(CMAKE_INSTALL_DIR)),
            ]

        out, _ = capfd.readouterr()
        for message in messages:
            assert message in out
def test_check_for_bad_installs(tmpdir):
    with push_dir(str(tmpdir)):
        tmpdir.ensure(CMAKE_BUILD_DIR(), "cmake_install.cmake").write(textwrap.dedent(
            """
            file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/../hello" TYPE FILE FILES "/path/to/hello/world.py")
            """
        ))
        with pytest.raises(SKBuildError) as excinfo:
            CMaker.check_for_bad_installs()
        assert "CMake-installed files must be within the project root" in str(excinfo.value)
Exemple #22
0
def test_distribution_is_pure(distribution_type, tmpdir):

    skbuild_setup_kwargs = {}

    if distribution_type == 'unknown':
        is_pure = False

    elif distribution_type == 'py_modules':
        is_pure = True
        hello_py = tmpdir.join("hello.py")
        hello_py.write("")
        skbuild_setup_kwargs["py_modules"] = ["hello"]

    elif distribution_type == 'packages':
        is_pure = True
        init_py = tmpdir.mkdir("hello").join("__init__.py")
        init_py.write("")
        skbuild_setup_kwargs["packages"] = ["hello"]

    elif distribution_type == 'skbuild':
        is_pure = False
        cmakelists_txt = tmpdir.join("CMakeLists.txt")
        cmakelists_txt.write(
            """
            cmake_minimum_required(VERSION 3.5.0)
            project(test NONE)
            install(CODE "execute_process(
              COMMAND \${CMAKE_COMMAND} -E sleep 0)")
            """
        )
    else:
        raise Exception(
            "Unknown distribution_type: {}".format(distribution_type))

    platform = get_platform()
    original_write_test_cmakelist = platform.write_test_cmakelist

    def write_test_cmakelist_no_languages(_self, _languages):
        original_write_test_cmakelist([])

    with patch.object(type(platform), 'write_test_cmakelist', new=write_test_cmakelist_no_languages):

        with push_dir(str(tmpdir)), push_argv(["setup.py", "build"]):
            distribution = skbuild_setup(
                name="test",
                version="0.0.1",
                description="test object returned by setup function",
                author="The scikit-build team",
                license="MIT",
                **skbuild_setup_kwargs
            )
            assert issubclass(distribution.__class__,
                              (distutils_Distribution, setuptool_Distribution))
            assert is_pure == distribution.is_pure()
Exemple #23
0
def test_distribution_is_pure(distribution_type, tmpdir):

    skbuild_setup_kwargs = {}

    if distribution_type == 'unknown':
        is_pure = False

    elif distribution_type == 'py_modules':
        is_pure = True
        hello_py = tmpdir.join("hello.py")
        hello_py.write("")
        skbuild_setup_kwargs["py_modules"] = ["hello"]

    elif distribution_type == 'packages':
        is_pure = True
        init_py = tmpdir.mkdir("hello").join("__init__.py")
        init_py.write("")
        skbuild_setup_kwargs["packages"] = ["hello"]

    elif distribution_type == 'skbuild':
        is_pure = False
        cmakelists_txt = tmpdir.join("CMakeLists.txt")
        cmakelists_txt.write(
            """
            cmake_minimum_required(VERSION 3.5.0)
            project(test NONE)
            install(CODE "execute_process(
              COMMAND \${CMAKE_COMMAND} -E sleep 0)")
            """
        )
    else:
        raise Exception(
            "Unknown distribution_type: {}".format(distribution_type))

    platform = get_platform()
    original_write_test_cmakelist = platform.write_test_cmakelist

    def write_test_cmakelist_no_languages(_self, _languages):
        original_write_test_cmakelist([])

    with patch.object(type(platform), 'write_test_cmakelist', new=write_test_cmakelist_no_languages):

        with push_dir(str(tmpdir)), push_argv(["setup.py", "build"]):
            distribution = skbuild_setup(
                name="test",
                version="0.0.1",
                description="test object returned by setup function",
                author="The scikit-build team",
                license="MIT",
                **skbuild_setup_kwargs
            )
            assert issubclass(distribution.__class__,
                              (distutils_Distribution, setuptool_Distribution))
            assert is_pure == distribution.is_pure()
Exemple #24
0
def test_hello_builds():
    with push_dir():

        @project_setup_py_test(("samples", "hello"), ["build"],
                               clear_cache=True)
        def run():
            pass

        # Check that a project can be build twice in a row
        # See issue scikit-build#120
        run()
        run()
Exemple #25
0
def test_configure_with_cmake_args(capfd):
    tmp_dir = _tmpdir('test_configure_with_cmake_args')
    with push_dir(str(tmp_dir)):

        tmp_dir.join('CMakeLists.txt').write(textwrap.dedent(
            """
            cmake_minimum_required(VERSION 3.5.0)
            project(foobar NONE)
            # Do not complain about missing arguments passed to the main
            # project
            foreach(unused_var IN ITEMS
              ${CMAKE_EXPECTED_BAR}
              ${CMAKE_EXPECTED_FOO}
              ${PYTHON_EXECUTABLE}
              ${PYTHON_INCLUDE_DIR}
              ${PYTHON_LIBRARY}
              ${PYTHON_VERSION_STRING}
              ${SKBUILD}
              )
            endforeach()
            """
        ))

        with push_dir(str(tmp_dir)):
            cmkr = CMaker()
            cmkr.configure(clargs=[
                '-DCMAKE_EXPECTED_FOO:STRING=foo',
                '-DCMAKE_EXPECTED_BAR:STRING=bar'
            ], cleanup=False)

        cmakecache = tmp_dir.join(
            "_cmake_test_compile", "build", "CMakeCache.txt")
        assert cmakecache.exists()
        variables = get_cmakecache_variables(str(cmakecache))
        assert variables.get('CMAKE_EXPECTED_FOO', (None, None))[1] == "foo"
        assert variables.get('CMAKE_EXPECTED_BAR', (None, None))[1] == "bar"

        unexpected = "Manually-specified variables were not used by the project"
        _, err = capfd.readouterr()
        assert unexpected not in err
def test_configure_with_cmake_args(capfd):
    tmp_dir = _tmpdir('test_configure_with_cmake_args')
    with push_dir(str(tmp_dir)):

        tmp_dir.join('CMakeLists.txt').write(textwrap.dedent(
            """
            cmake_minimum_required(VERSION 3.5.0)
            project(foobar NONE)
            # Do not complain about missing arguments passed to the main
            # project
            foreach(unused_var IN ITEMS
              ${CMAKE_EXPECTED_BAR}
              ${CMAKE_EXPECTED_FOO}
              ${PYTHON_EXECUTABLE}
              ${PYTHON_INCLUDE_DIR}
              ${PYTHON_LIBRARY}
              ${PYTHON_VERSION_STRING}
              ${SKBUILD}
              )
            endforeach()
            """
        ))

        with push_dir(str(tmp_dir)):
            cmkr = CMaker()
            cmkr.configure(clargs=[
                '-DCMAKE_EXPECTED_FOO:STRING=foo',
                '-DCMAKE_EXPECTED_BAR:STRING=bar'
            ], cleanup=False)

        cmakecache = tmp_dir.join(
            "_cmake_test_compile", "build", "CMakeCache.txt")
        assert cmakecache.exists()
        variables = get_cmakecache_variables(str(cmakecache))
        assert variables.get('CMAKE_EXPECTED_FOO', (None, None))[1] == "foo"
        assert variables.get('CMAKE_EXPECTED_BAR', (None, None))[1] == "bar"

        unexpected = "Manually-specified variables were not used by the project"
        _, err = capfd.readouterr()
        assert unexpected not in err
Exemple #27
0
def test_push_dir(tmpdir):
    old_cwd = os.getcwd()
    try:
        level1 = tmpdir.mkdir("level1")
        level2 = level1.mkdir("level2")

        os.chdir(str(level2))
        assert os.path.split(os.getcwd())[-1] == 'level2'

        # No directory
        with push_dir():
            os.chdir(os.path.join(os.getcwd(), '..'))
            assert os.path.split(os.getcwd())[-1] == 'level1'
        assert os.path.split(os.getcwd())[-1] == 'level2'

        # With existing directory
        with push_dir(directory=os.path.join(os.getcwd(), '..')):
            assert os.path.split(os.getcwd())[-1] == 'level1'
        assert os.path.split(os.getcwd())[-1] == 'level2'

        foo_directory = os.path.join(str(tmpdir), 'foo')

        # With non existing directory
        failed = False
        try:
            with push_dir(directory=foo_directory):
                pass
        except OSError:
            failed = True
        assert failed
        assert not os.path.isdir(foo_directory)

        # With make_directory option
        with push_dir(directory=foo_directory, make_directory=True):
            assert os.getcwd() == foo_directory
        assert os.path.split(os.getcwd())[-1] == 'level2'
        assert os.path.isdir(foo_directory)
    finally:
        os.chdir(old_cwd)
Exemple #28
0
def test_push_dir(tmpdir):
    old_cwd = os.getcwd()
    try:
        level1 = tmpdir.mkdir("level1")
        level2 = level1.mkdir("level2")

        os.chdir(str(level2))
        assert os.path.split(os.getcwd())[-1] == 'level2'

        # No directory
        with push_dir():
            os.chdir(os.path.join(os.getcwd(), '..'))
            assert os.path.split(os.getcwd())[-1] == 'level1'
        assert os.path.split(os.getcwd())[-1] == 'level2'

        # With existing directory
        with push_dir(directory=os.path.join(os.getcwd(), '..')):
            assert os.path.split(os.getcwd())[-1] == 'level1'
        assert os.path.split(os.getcwd())[-1] == 'level2'

        foo_directory = os.path.join(str(tmpdir), 'foo')

        # With non existing directory
        failed = False
        try:
            with push_dir(directory=foo_directory):
                pass
        except OSError:
            failed = True
        assert failed
        assert not os.path.isdir(foo_directory)

        # With make_directory option
        with push_dir(directory=foo_directory, make_directory=True):
            assert os.getcwd() == foo_directory
        assert os.path.split(os.getcwd())[-1] == 'level2'
        assert os.path.isdir(foo_directory)
    finally:
        os.chdir(old_cwd)
def test_too_many_separators():
    with push_dir():

        @project_setup_py_test("hello-no-language", ["--"] * 3, disable_languages_test=True)
        def run():
            pass

        failed = False
        try:
            run()
        except SystemExit as e:
            failed = e.args[0].startswith('ERROR: Too many')

        assert failed
def test_too_many_separators():
    with push_dir():

        @project_setup_py_test("hello", ["--"] * 3)
        def run():
            pass

        failed = False
        try:
            run()
        except SystemExit as e:
            failed = e.args[0].startswith('ERROR: Too many')

        assert failed
def test_too_many_separators():
    with push_dir():

        @project_setup_py_test(("samples", "hello"), ["--"] * 3)
        def run():
            pass

        failed = False
        try:
            run()
        except SystemExit as e:
            failed = e.args[0].startswith('ERROR: Too many')

        assert failed
def test_no_command():
    with push_dir():

        @project_setup_py_test("hello", [])
        def run():
            pass

        failed = False
        try:
            run()
        except SystemExit as e:
            failed = 'error: no commands supplied' in e.args[0]

        assert failed
        assert not os.path.exists('_skbuild')
def test_no_command():
    with push_dir():

        @project_setup_py_test("hello-no-language", [], disable_languages_test=True)
        def run():
            pass

        failed = False
        try:
            run()
        except SystemExit as e:
            failed = 'error: no commands supplied' in e.args[0]

        assert failed
        assert not os.path.exists('_skbuild')
def test_invalid_command():

    with push_dir():

        @project_setup_py_test("hello", ["unknown"])
        def run():
            pass

        failed = False
        try:
            run()
        except SystemExit as e:
            failed = 'error: invalid command' in e.args[0]

        assert failed
        assert not os.path.exists('_skbuild')
def test_no_command():
    with push_dir():

        @project_setup_py_test(("samples", "hello"), [],
                               clear_cache=True)
        def run():
            pass

        failed = False
        try:
            run()
        except SystemExit as e:
            failed = 'error: no commands supplied' in e.args[0]

        assert failed
        assert not os.path.exists('_skbuild')
Exemple #36
0
def test_hello_builds():
    with push_dir():

        @project_setup_py_test("hello-cpp", ["build"])
        def run():
            pass

        # Check that a project can be build twice in a row
        # See issue scikit-build#120
        tmp_dir = run()[0]

        @project_setup_py_test("hello-cpp", ["build"], tmp_dir=tmp_dir)
        def another_run():
            pass

        another_run()
Exemple #37
0
def test_hello_builds():
    with push_dir():

        @project_setup_py_test("hello", ["build"])
        def run():
            pass

        # Check that a project can be build twice in a row
        # See issue scikit-build#120
        tmp_dir = run()[0]

        @project_setup_py_test("hello", ["build"], tmp_dir=tmp_dir)
        def another_run():
            pass

        another_run()
Exemple #38
0
def execute_setup_py(project_dir, setup_args, disable_languages_test=False):
    """Context manager executing ``setup.py`` with the given arguments.

    It yields after changing the current working directory
    to ``project_dir``.
    """

    # See https://stackoverflow.com/questions/9160227/dir-util-copy-tree-fails-after-shutil-rmtree
    distutils.dir_util._path_created = {}

    # Clear _PYTHON_HOST_PLATFORM to ensure value sets in skbuild.setuptools_wrap.setup() does not
    # influence other tests.
    if '_PYTHON_HOST_PLATFORM' in os.environ:
        del os.environ['_PYTHON_HOST_PLATFORM']

    with push_dir(str(project_dir)), push_argv(["setup.py"] +
                                               setup_args), prepend_sys_path(
                                                   [str(project_dir)]):

        # Restore master working set that is reset following call to "python setup.py test"
        # See function "project_on_sys_path()" in setuptools.command.test
        pkg_resources._initialize_master_working_set()

        with open("setup.py", "r") as fp:
            setup_code = compile(fp.read(), "setup.py", mode="exec")

            if setup_code is not None:

                if disable_languages_test:

                    platform = get_platform()
                    original_write_test_cmakelist = platform.write_test_cmakelist

                    def write_test_cmakelist_no_languages(_self, _languages):
                        original_write_test_cmakelist([])

                    with patch.object(type(platform),
                                      'write_test_cmakelist',
                                      new=write_test_cmakelist_no_languages):
                        six.exec_(setup_code)

                else:
                    six.exec_(setup_code)

        yield
Exemple #39
0
def execute_setup_py(project_dir, setup_args):
    """Context manager executing ``setup.py`` with the given arguments.

    It yields after changing the current working directory
    to ``project_dir``.
    """

    with push_dir(str(project_dir)), \
            push_argv(["setup.py"] + setup_args):
        setup_code = None

        with open("setup.py", "r") as fp:
            setup_code = compile(fp.read(), "setup.py", mode="exec")

        if setup_code is not None:
            six.exec_(setup_code)

        yield
def test_first_invalid_generator(mocker, capfd):
    platform = get_platform()
    default_generators = [CMakeGenerator('Invalid')]
    default_generators.extend(platform.default_generators)
    mocker.patch.object(type(platform), 'default_generators',
                        new_callable=mocker.PropertyMock,
                        return_value=default_generators)

    mocker.patch('skbuild.cmaker.get_platform', return_value=platform)

    with push_dir(), push_env(CMAKE_GENERATOR=None):
        @project_setup_py_test("hello-no-language", ["build"])
        def run_build():
            pass

        run_build()

    _, err = capfd.readouterr()
    assert "CMake Error: Could not create named generator Invalid" in err
Exemple #41
0
def test_first_invalid_generator(mocker, capfd):
    platform = get_platform()
    default_generators = [CMakeGenerator('Invalid')]
    default_generators.extend(platform.default_generators)
    mocker.patch.object(type(platform), 'default_generators',
                        new_callable=mocker.PropertyMock,
                        return_value=default_generators)

    mocker.patch('skbuild.cmaker.get_platform', return_value=platform)

    with push_dir(), push_env(CMAKE_GENERATOR=None):
        @project_setup_py_test("hello-no-language", ["build"])
        def run_build():
            pass

        run_build()

    _, err = capfd.readouterr()
    assert "CMake Error: Could not create named generator Invalid" in err
Exemple #42
0
def execute_setup_py(project_dir, setup_args, disable_languages_test=False):
    """Context manager executing ``setup.py`` with the given arguments.

    It yields after changing the current working directory
    to ``project_dir``.
    """

    # See https://stackoverflow.com/questions/9160227/dir-util-copy-tree-fails-after-shutil-rmtree
    distutils.dir_util._path_created = {}

    # Clear _PYTHON_HOST_PLATFORM to ensure value sets in skbuild.setuptools_wrap.setup() does not
    # influence other tests.
    if '_PYTHON_HOST_PLATFORM' in os.environ:
        del os.environ['_PYTHON_HOST_PLATFORM']

    with push_dir(str(project_dir)), push_argv(["setup.py"] + setup_args), prepend_sys_path([str(project_dir)]):

        # Restore master working set that is reset following call to "python setup.py test"
        # See function "project_on_sys_path()" in setuptools.command.test
        pkg_resources._initialize_master_working_set()

        with open("setup.py", "r") as fp:
            setup_code = compile(fp.read(), "setup.py", mode="exec")

            if setup_code is not None:

                if disable_languages_test:

                    platform = get_platform()
                    original_write_test_cmakelist = platform.write_test_cmakelist

                    def write_test_cmakelist_no_languages(_self, _languages):
                        original_write_test_cmakelist([])

                    with patch.object(type(platform), 'write_test_cmakelist', new=write_test_cmakelist_no_languages):
                        six.exec_(setup_code)

                else:
                    six.exec_(setup_code)

        yield
def test_cmakelists_with_fatalerror_fails(capfd):

    with push_dir():

        @project_setup_py_test("fail-with-fatal-error-cmakelists", ["build"], disable_languages_test=True)
        def should_fail():
            pass

        failed = False
        message = ""
        try:
            should_fail()
        except SystemExit as e:
            failed = isinstance(e.code, SKBuildError)
            message = str(e)

    assert failed

    _, err = capfd.readouterr()
    assert "Invalid CMakeLists.txt" in err
    assert "An error occurred while configuring with CMake." in message
def test_hello_clean(capfd):
    with push_dir():

        @project_setup_py_test("hello-pure", ["build"])
        def run_build():
            pass

        tmp_dir = run_build()[0]

        assert tmp_dir.join(SKBUILD_DIR).exists()

        @project_setup_py_test("hello-pure", ["clean"], tmp_dir=tmp_dir)
        def run_clean():
            pass

        run_clean()

        assert not tmp_dir.join(SKBUILD_DIR).exists()

        out = capfd.readouterr()[0]
        assert 'Build files have been written to' not in out
def test_cmakelists_with_syntaxerror_fails(capfd):

    with push_dir():

        @project_setup_py_test("fail-with-syntax-error-cmakelists", ["build"], disable_languages_test=True)
        def should_fail():
            pass

        failed = False
        message = ""
        try:
            should_fail()
        except SystemExit as e:
            failed = isinstance(e.code, SKBuildError)
            message = str(e)

    assert failed

    _, err = capfd.readouterr()
    assert "Parse error.  Function missing ending \")\"" in err
    assert "An error occurred while configuring with CMake." in message
def test_hello_with_compileerror_fails(capfd):

    with push_dir():

        @project_setup_py_test("fail-hello-with-compile-error", ["build"])
        def should_fail():
            pass

        failed = False
        message = ""
        try:
            should_fail()
        except SystemExit as e:
            failed = isinstance(e.code, SKBuildError)
            message = str(e)

    assert failed

    out, err = capfd.readouterr()
    assert "_hello.cxx" in out or "_hello.cxx" in err
    assert "An error occurred while building with CMake." in message
Exemple #47
0
def test_hello_clean(capfd):
    with push_dir():

        @project_setup_py_test("hello-pure", ["build"], disable_languages_test=True)
        def run_build():
            pass

        tmp_dir = run_build()[0]

        assert tmp_dir.join(SKBUILD_DIR()).exists()

        @project_setup_py_test("hello-pure", ["clean"], tmp_dir=tmp_dir, disable_languages_test=True)
        def run_clean():
            pass

        run_clean()

        assert not tmp_dir.join(SKBUILD_DIR()).exists()

        out = capfd.readouterr()[0]
        assert 'Build files have been written to' not in out
Exemple #48
0
def test_cmakelists_with_fatalerror_fails(capfd):

    with push_dir():

        @project_setup_py_test("fail-with-fatal-error-cmakelists", ["build"])
        def should_fail():
            pass

        failed = False
        message = ""
        try:
            should_fail()
        except SystemExit as e:
            failed = isinstance(e.code, SKBuildError)
            message = str(e)

    assert failed

    _, err = capfd.readouterr()
    assert "Invalid CMakeLists.txt" in err
    assert "An error occurred while configuring with CMake." in message
Exemple #49
0
def test_cmakelists_with_syntaxerror_fails(capfd):

    with push_dir():

        @project_setup_py_test("fail-with-syntax-error-cmakelists", ["build"])
        def should_fail():
            pass

        failed = False
        message = ""
        try:
            should_fail()
        except SystemExit as e:
            failed = isinstance(e.code, SKBuildError)
            message = str(e)

    assert failed

    _, err = capfd.readouterr()
    assert "Parse error.  Function missing ending \")\"" in err
    assert "An error occurred while configuring with CMake." in message
Exemple #50
0
def test_hello_with_compileerror_fails(capfd):

    with push_dir():

        @project_setup_py_test("fail-hello-with-compile-error", ["build"])
        def should_fail():
            pass

        failed = False
        message = ""
        try:
            should_fail()
        except SystemExit as e:
            failed = isinstance(e.code, SKBuildError)
            message = str(e)

    assert failed

    out, err = capfd.readouterr()
    assert "_hello.cxx" in out or "_hello.cxx" in err
    assert "An error occurred while building with CMake." in message
Exemple #51
0
def test_hello_clean(dry_run, capfd):
    with push_dir():

        dry_run = dry_run == 'with-dry-run'

        skbuild_dir = os.path.join("tests", "samples", "hello", SKBUILD_DIR)

        @project_setup_py_test(("samples", "hello"), ["build"],
                               clear_cache=True)
        def run_build():
            pass

        run_build()

        assert os.path.exists(skbuild_dir)

        # XXX Since using capfd.disabled() context manager prevents
        # the output from being captured atfer it exits, we display
        # a separator allowing to differentiate the build and clean output.
        print("<<-->>")

        clean_args = ["clean"]
        if dry_run:
            clean_args.append("--dry-run")

        @project_setup_py_test(("samples", "hello"), clean_args)
        def run_clean():
            pass

        run_clean()

        if not dry_run:
            assert not os.path.exists(skbuild_dir)
        else:
            assert os.path.exists(skbuild_dir)

        build_out, clean_out = capfd.readouterr()[0].split('<<-->>')
        assert 'Build files have been written to' in build_out
        assert 'Build files have been written to' not in clean_out
Exemple #52
0
def test_hello_clean(dry_run, capfd):
    with push_dir():

        dry_run = dry_run == 'with-dry-run'

        @project_setup_py_test("hello", ["build"])
        def run_build():
            pass

        tmp_dir = run_build()[0]

        assert tmp_dir.join(SKBUILD_DIR).exists()

        # XXX Since using capfd.disabled() context manager prevents
        # the output from being captured atfer it exits, we display
        # a separator allowing to differentiate the build and clean output.
        print("<<-->>")

        clean_args = ["clean"]
        if dry_run:
            clean_args.append("--dry-run")

        @project_setup_py_test("hello", clean_args, tmp_dir=tmp_dir)
        def run_clean():
            pass

        run_clean()

        if not dry_run:
            assert not tmp_dir.join(SKBUILD_DIR).exists()
        else:
            assert tmp_dir.join(SKBUILD_DIR).exists()

        build_out, clean_out = capfd.readouterr()[0].split('<<-->>')
        assert 'Build files have been written to' in build_out
        assert 'Build files have been written to' not in clean_out
Exemple #53
0
def test_hello_cleans(capfd):
    with push_dir():

        tmp_dir = _tmpdir("test_hello_cleans")

        _copy_dir(tmp_dir, os.path.join(SAMPLES_DIR, "hello"))

        @project_setup_py_test("hello", ["build"], tmp_dir=tmp_dir)
        def run_build():
            pass

        @project_setup_py_test("hello", ["clean"], tmp_dir=tmp_dir)
        def run_clean():
            pass

        # Check that a project can be cleaned twice in a row
        run_build()
        print("<<-->>")
        run_clean()
        print("<<-->>")
        run_clean()

    _, clean1_out, clean2_out = \
        capfd.readouterr()[0].split('<<-->>')

    clean1_out = clean1_out.strip()
    clean2_out = clean2_out.strip()

    assert "running clean" == clean1_out.splitlines()[0]
    assert "removing '_skbuild{}cmake-install'".format(os.path.sep) \
           == clean1_out.splitlines()[1]
    assert "removing '_skbuild{}cmake-build'".format(os.path.sep) \
           == clean1_out.splitlines()[2]
    assert "removing '_skbuild'" == clean1_out.splitlines()[3]

    assert "running clean" == clean2_out
Exemple #54
0
def test_hello_clean(dry_run, capfd):
    with push_dir():

        dry_run = dry_run == 'with-dry-run'

        @project_setup_py_test("hello-cpp", ["build"])
        def run_build():
            pass

        tmp_dir = run_build()[0]

        assert tmp_dir.join(SKBUILD_DIR()).exists()

        # XXX Since using capfd.disabled() context manager prevents
        # the output from being captured atfer it exits, we display
        # a separator allowing to differentiate the build and clean output.
        print("<<-->>")

        clean_args = ["clean"]
        if dry_run:
            clean_args.append("--dry-run")

        @project_setup_py_test("hello-cpp", clean_args, tmp_dir=tmp_dir)
        def run_clean():
            pass

        run_clean()

        if not dry_run:
            assert not tmp_dir.join(SKBUILD_DIR()).exists()
        else:
            assert tmp_dir.join(SKBUILD_DIR()).exists()

        build_out, clean_out = capfd.readouterr()[0].split('<<-->>')
        assert 'Build files have been written to' in build_out
        assert 'Build files have been written to' not in clean_out
Exemple #55
0
def execute_setup_py(project_dir, setup_args, disable_languages_test=False):
    """Context manager executing ``setup.py`` with the given arguments.

    It yields after changing the current working directory
    to ``project_dir``.
    """

    # See https://stackoverflow.com/questions/9160227/dir-util-copy-tree-fails-after-shutil-rmtree
    distutils.dir_util._path_created = {}

    with push_dir(str(project_dir)), push_argv(["setup.py"] +
                                               setup_args), prepend_sys_path(
                                                   [str(project_dir)]):

        with open("setup.py", "r") as fp:
            setup_code = compile(fp.read(), "setup.py", mode="exec")

            if setup_code is not None:

                if disable_languages_test:

                    platform = get_platform()
                    original_write_test_cmakelist = platform.write_test_cmakelist

                    def write_test_cmakelist_no_languages(_self, _languages):
                        original_write_test_cmakelist([])

                    with patch.object(type(platform),
                                      'write_test_cmakelist',
                                      new=write_test_cmakelist_no_languages):
                        six.exec_(setup_code)

                else:
                    six.exec_(setup_code)

        yield
def test_make_without_build_dir_fails():
    src_dir = _tmpdir('test_make_without_build_dir_fails')
    with push_dir(str(src_dir)), pytest.raises(SKBuildError) as excinfo:
        CMaker().make()
    assert "Did you forget to run configure before make" in str(excinfo.value)