Exemple #1
0
def _exec_cmd(
    project: Project,
    logger: Logger,
    reactor: Reactor,
    program: str,
    *arguments: str,
    message: str = None,
    error: str = None,
    report_file: str = None,
    verbose_property: str = None,
    force_log: bool = False,
) -> Optional[ExternalCommandResult]:
    report_folder = _make_folder(project, "$dir_reports", "docker")
    report_file = report_file or "_".join([program, *arguments])

    command = ExternalCommandBuilder(program, project, reactor)
    for argument in arguments:
        command.use_argument(argument)
    if message:
        logger.info(message)
    result = command.run(f"{report_folder}/{report_file}")
    if result.exit_code == 0:
        return result

    is_verbose = project.get_property("verbose", False)
    is_verbose_property = verbose_property and project.get_property(
        verbose_property, False)
    if force_log or is_verbose or is_verbose_property:
        logger.error(result.error_report_lines)
    if error:
        raise Exception(error)
class FlakePluginInitializationTests(TestCase):

    def setUp(self):
        self.project = Project("basedir")

    def test_should_set_dependency(self):
        mock_project = Mock(Project)
        initialize_flake8_plugin(mock_project)
        mock_project.build_depends_on.assert_called_with('flake8')

    def test_should_leave_user_specified_properties_when_initializing_plugin(self):

        expected_properties = {
            "flake8_break_build": True,
            "flake8_max_line_length": 80,
            "flake8_exclude_patterns": ".svn",
            "flake8_include_test_sources": True,
            "flake8_include_scripts": True
            }
        for property_name, property_value in expected_properties.items():
            self.project.set_property(property_name, property_value)

            initialize_flake8_plugin(self.project)

        for property_name, property_value in expected_properties.items():
            self.assertEquals(
                self.project.get_property("flake8_break_build"), True)
            self.assertEquals(
                self.project.get_property("flake8_max_line_length"), 80)
            self.assertEquals(
                self.project.get_property("flake8_exclude_patterns"), ".svn")
            self.assertEquals(
                self.project.get_property("flake8_include_test_sources"), True)
            self.assertEquals(
                self.project.get_property("flake8_include_scripts"), True)
 def test_initialize_sets_variables_correctly(self):
     project = Project(".")
     initialize_plugin(project)
     self.assertEqual(project.get_property("lambda_file_access_control"), "bucket-owner-full-control")
     self.assertEqual(project.get_property("bucket_prefix"), "")
     self.assertEqual(project.get_property("template_file_access_control"), "bucket-owner-full-control")
     self.assertEqual(project.get_property("template_key_prefix"), "")
Exemple #4
0
class PytestPluginInitializationTests(TestCase):
    """ Test initialize_pytest_plugin"""
    def setUp(self):
        self.project = Project("basedir")

    def test_should_set_dependency(self):  # pylint: disable=no-self-use
        """ Test dependencies"""
        mock_project = Mock(Project)
        initialize_pytest_plugin(mock_project)
        mock_project.plugin_depends_on.assert_called_with('pytest')

    def test_should_set_default_properties(self):   # pylint: disable=invalid-name
        """ Test default properties"""
        initialize_pytest_plugin(self.project)
        expected_default_properties = {
            'dir_source_pytest_python': "src/unittest/python",
            'pytest_extra_args': []}
        for prop_name, prop_value in expected_default_properties.items():
            self.assertEquals(
                self.project.get_property(prop_name), prop_value)

    def test_should_leave_user_specified_properties(self):  # pylint: disable=invalid-name
        """ Test that user-specified properties override defaults"""
        expected_properties = {
            "dir_source_pytest_python": "some/path"
            }
        for property_name, property_value in expected_properties.items():
            self.project.set_property(property_name, property_value)

        initialize_pytest_plugin(self.project)

        for property_name, property_value in expected_properties.items():
            self.assertEquals(self.project.get_property(property_name),
                              property_value)
class CoveragePluginTests(TestCase):
    def setUp(self):
        self.project = Project("basedir")

    def test_should_leave_user_specified_properties_when_initializing_plugin(
            self):

        expected_properties = {
            "coverage_threshold_warn": 120,
            "coverage_break_build": False,
            "coverage_reload_modules": False,
            "coverage_exceptions": ["foo"],
            "coverage_fork": True
        }

        for property_name, property_value in expected_properties.items():
            self.project.set_property(property_name, property_value)

            init_coverage_properties(self.project)

        for property_name, property_value in expected_properties.items():
            self.assertEquals(
                self.project.get_property("coverage_threshold_warn"), 120)
            self.assertEquals(
                self.project.get_property("coverage_break_build"), False)
            self.assertEquals(
                self.project.get_property("coverage_reload_modules"), False)
            self.assertEquals(self.project.get_property("coverage_exceptions"),
                              ["foo"])
            self.assertEquals(self.project.get_property("coverage_fork"), True)
Exemple #6
0
class PytestPluginInitializationTests(TestCase):
    def setUp(self):
        self.project = Project("basedir")
        self.project.set_property("pytest_extra_args", ["pytest_stub"])
        self.project.set_property("dir_source_main_python", "")

    def test_should_set_default_properties(self):
        initialize_pytest_coverage(self.project)
        expected_default_properties = {
            "pytest_coverage_skip_covered": False,
            "pytest_coverage_xml": False,
            "pytest_coverage_html": False,
            "pytest_coverage_annotate": False,
            "pytest_coverage_break_build_threshold": 0
        }
        for property_name, property_value in expected_default_properties.items(
        ):
            self.assertEquals(self.project.get_property(property_name),
                              property_value)

    def test_should_set_enable_default_properties(self):
        initialize_pytest_coverage(self.project)
        enable_pytest_coverage(self.project, Mock())
        self.assertEquals(
            self.project.get_property("pytest_extra_args"),
            ["pytest_stub", "--cov-branch", "--cov-report=term-missing"])

    @patch("pybuilder_pytest_coverage.discover_modules",
           return_value=['module1', 'module2'])
    def test_should_leave_user_specified_properties_when_initializing_plugin(
            self, discover_modules):
        self.project.set_property("dir_reports", "target/reports")
        expected_properties = {
            "pytest_coverage_skip_covered": True,
            "pytest_coverage_xml": True,
            "pytest_coverage_html": True,
            "pytest_coverage_annotate": True,
            "pytest_coverage_break_build_threshold": 50
        }
        for property_name, property_value in expected_properties.items():
            self.project.set_property(property_name, property_value)

        initialize_pytest_coverage(self.project)

        for property_name, property_value in expected_properties.items():
            self.assertEquals(self.project.get_property(property_name),
                              property_value)

        enable_pytest_coverage(self.project, Mock())

        self.assertEquals(self.project.get_property("pytest_extra_args"), [
            "pytest_stub", "--cov=module1", "--cov=module2", "--cov-branch",
            "--cov-report=term-missing:skip-covered",
            "--cov-report=xml:basedir/target/reports/pytest_coverage.xml",
            "--cov-report=html:basedir/target/reports/pytest_coverage_html",
            "--cov-report=annotate:basedir/target/reports/pytest_coverage_annotate",
            "--cov-fail-under=50"
        ])
Exemple #7
0
class UtilsTest(unittest.TestCase):
    def setUp(self):
        self.project = Project('/path/to/project')
        self.project.set_property('dir_source_unittest_python',
                                  'src/unittest/python')
        self.project.set_property('dir_source_main_python', 'src/main/python')
        self.project.set_property('dir_target', 'target')

    def test_importDirs(self):
        cwd = os.getcwd()

        dirs = utils.getImportantDirs(self.project)

        # src_dir
        self.assertEquals(
            dirs[0],
            cwd + "/" + self.project.get_property('dir_source_main_python'))

        # test_dir
        self.assertEquals(
            dirs[1], cwd + "/" +
            self.project.get_property('dir_source_unittest_python'))

        # html_dir
        self.assertEquals(dirs[2], cwd + "/target/reports/coverage_html")

        # xml_file
        self.assertEquals(dirs[3], cwd + "/target/reports/coverage.xml")

        # xunit_file
        self.assertEquals(dirs[4], cwd + "/target/reports/coverage.xunit.xml")

    def test_prepareArgs(self):
        self.project.set_property('nose_numeric', 1)
        self.project.set_property('nose_string', 'foobar')
        self.project.set_property('nose_array', ['one', 'two', 'three'])
        self.project.set_property('nose_true', True)
        self.project.set_property('nose_true-array', [True, True])

        self.project.set_property('nose_unused1', False)
        self.project.set_property('nose_unused2', None)

        args = utils.prepareArgs(self.project)

        self.assertEquals(len(args), 8)

        self.assertEquals('--numeric' in args, True)
        self.assertEquals('--string=foobar' in args, True)
        self.assertEquals('--array=one' in args, True)
        self.assertEquals('--array=two' in args, True)
        self.assertEquals('--array=three' in args, True)
        self.assertEquals('--true' in args, True)
        self.assertEquals('--true-array' in args, True)
        self.assertEquals('--true-array' in args, True)
Exemple #8
0
 def test_initialize_sets_variables_correctly(self):
     project = Project(".")
     initialize_plugin(project)
     self.assertEqual(
         project.get_property(emr_tasks.PROPERTY_S3_FILE_ACCESS_CONTROL),
         "bucket-owner-full-control")
     self.assertEqual(
         project.get_property(emr_tasks.PROPERTY_S3_BUCKET_PREFIX), "")
     self.assertEqual(
         project.get_property(emr_tasks.PROPERTY_S3_RELEASE_PREFIX),
         emr_tasks.RELEASE_PREFIX_DEFAULT)
 def test_initialize_sets_variables_correctly(self):
     project = Project('.')
     initialize_plugin(project)
     self.assertEqual(project.get_property('lambda_file_access_control'),
                      'bucket-owner-full-control')
     self.assertEqual(project.get_property('bucket_prefix'),
                      '')
     self.assertEqual(project.get_property('template_file_access_control'),
                      'bucket-owner-full-control')
     self.assertEqual(project.get_property('template_key_prefix'),
                      '')
class UtilsTest(unittest.TestCase):

  def setUp(self):
    self.project = Project('/path/to/project')
    self.project.set_property('dir_source_unittest_python', 'src/unittest/python')
    self.project.set_property('dir_source_main_python', 'src/main/python')
    self.project.set_property('dir_target','target')

  def test_importDirs(self):
    cwd = os.getcwd()
    
    dirs = utils.getImportantDirs(self.project)
    
    # src_dir
    self.assertEquals(dirs[0], cwd + "/" + self.project.get_property('dir_source_main_python'))

    # test_dir
    self.assertEquals(dirs[1], cwd + "/" + self.project.get_property('dir_source_unittest_python'))

    # html_dir
    self.assertEquals(dirs[2], cwd + "/target/reports/coverage_html")

    # xml_file
    self.assertEquals(dirs[3], cwd + "/target/reports/coverage.xml")

    # xunit_file
    self.assertEquals(dirs[4], cwd + "/target/reports/coverage.xunit.xml")

  def test_prepareArgs(self):
    self.project.set_property('nose_numeric', 1)
    self.project.set_property('nose_string', 'foobar')
    self.project.set_property('nose_array', ['one','two','three'])
    self.project.set_property('nose_true', True)
    self.project.set_property('nose_true-array', [True, True])
    
    self.project.set_property('nose_unused1', False)
    self.project.set_property('nose_unused2', None)

    args = utils.prepareArgs(self.project)

    self.assertEquals(len(args), 8)

    self.assertEquals('--numeric' in args, True)
    self.assertEquals('--string=foobar' in args, True)
    self.assertEquals('--array=one' in args, True)
    self.assertEquals('--array=two' in args, True)
    self.assertEquals('--array=three' in args, True)
    self.assertEquals('--true' in args, True)
    self.assertEquals('--true-array' in args, True)
    self.assertEquals('--true-array' in args, True)
Exemple #11
0
def _do_docker_push(project: Project, logger: Logger,
                    reactor: Reactor) -> None:
    project.set_property_if_unset("docker_push_verbose_output",
                                  project.get_property("verbose"))

    registry = project.get_mandatory_property("docker_push_registry")
    local_img = project.get_property("docker_package_build_img",
                                     f"{project.name}:{project.version}")
    fq_artifact = project.get_property("docker_push_img", local_img)
    registry_path = f"{registry}/{fq_artifact}"

    _docker_login_aws_ecr(project, logger, reactor, registry, fq_artifact)
    _docker_tag_and_push_image(project, logger, reactor, local_img)
    _generate_artifact_manifest(project, logger, reactor, registry_path)
def _run_tavern_tests_in_dir(test_dir: str,
                             logger: Logger,
                             project: Project,
                             reactor: Reactor,
                             role=None):
    logger.info("Running tavern tests: {}".format(test_dir))
    if not os.path.exists(test_dir):
        logger.info("Skipping tavern run: no tests")
        return False
    logger.info(
        f"Found {len(os.listdir(test_dir))} files in tavern test directory")
    # todo is this unique enough for each run?
    output_file, run_name = get_test_report_file(project, test_dir)
    from sys import path as syspath
    syspath.insert(0, test_dir)
    # install any requirements that my exist
    requirements_file = os.path.join(test_dir, "requirements.txt")
    if os.path.exists(requirements_file):
        dependency = RequirementsFile(requirements_file)
        install_dependencies(
            logger, project, dependency, reactor.pybuilder_venv,
            f"{prepare_logs_directory(project)}/install_tavern_pip_dependencies.log"
        )
    extra_args = [
        project.expand(prop)
        for prop in project.get_property(TAVERN_ADDITIONAL_ARGS, [])
    ]
    args = ["--junit-xml", f"{output_file}", test_dir] + extra_args
    if project.get_property("verbose"):
        args.append("-s")
        args.append("-v")
    os.environ['TARGET'] = project.get_property(INTEGRATION_TARGET_URL)
    os.environ[ENVIRONMENT] = project.get_property(ENVIRONMENT)
    logger.info(
        f"Running against: {project.get_property(INTEGRATION_TARGET_URL)} ")
    cache_wd = os.getcwd()
    try:
        os.chdir(test_dir)
        ret = pytest.main(args)
    finally:
        os.chdir(cache_wd)
    if role:
        CloudwatchLogs(project.get_property(ENVIRONMENT),
                       project.get_property(APPLICATION), role,
                       logger).print_latest()
    if ret != 0:
        raise BuildFailedException(
            f"Tavern tests failed see complete output here - {output_file}")
    return True
Exemple #13
0
def set_properties(project: Project):
    # Dependencies
    project.depends_on("gevent")

    project.build_depends_on("wsaccel")
    project.build_depends_on("ujson")
    project.build_depends_on("websocket-client", "~=0.0")
    project.build_depends_on("gunicorn")

    # Cram Configuration
    project.set_property("cram_fail_if_no_tests", False)

    # Disable flake8
    project.set_property("flake8_break_build", False)

    # Integration Tests Coverage is disabled since there are no integration tests
    project.set_property("unittest_coverage_threshold_warn", 0)
    project.set_property("unittest_coverage_branch_threshold_warn", 0)
    project.set_property("unittest_coverage_branch_partial_threshold_warn", 0)
    project.set_property("unittest_coverage_allow_non_imported_modules", True)
    project.set_property("integrationtest_coverage_threshold_warn", 0)
    project.set_property("integrationtest_coverage_branch_threshold_warn", 0)
    project.set_property(
        "integrationtest_coverage_branch_partial_threshold_warn", 0)
    project.set_property("integrationtest_coverage_allow_non_imported_modules",
                         True)

    project.set_property("pybuilder_header_plugin_break_build", False)

    project.set_property("copy_resources_target", "$dir_dist")
    project.get_property("copy_resources_glob").append("LICENSE")
    project.get_property("filter_resources_glob").append(
        "**/geventwebsocket/__init__.py")

    # Distutils
    project.set_property(
        "distutils_classifiers",
        project.get_property("distutils_classifiers") + [
            'Programming Language :: Python :: 3.3',
            'Programming Language :: Python :: 3.4',
            'Programming Language :: Python :: 3.5',
            'Programming Language :: Python :: 3.6',
            'Topic :: Software Development :: Libraries',
            'Topic :: Software Development :: Libraries :: Python Modules',
            'Topic :: Internet',
        ])

    project.set_property("pdoc_module_name", "geventwebsocket")
def verify_tavern(project: Project, logger: Logger, reactor: Reactor):
    # Expand the directory to get full path
    test_dir = project.expand_path(f"${TAVERN_TEST_DIR}")
    # Run the tests in the directory
    if _run_tavern_tests_in_dir(test_dir, logger, project, reactor):
        package_artifacts(project, test_dir, "tavern",
                          project.get_property(ROLE))
def get_project_metadata(logger: Logger, project: Project):
    app_group, app_name, role = extract_application_role(logger, project)
    environment = project.get_mandatory_property(ENVIRONMENT)
    bucket = project.get_property(
        INTEGRATION_ARTIFACT_BUCKET,
        f"integration-artifacts-{app_group}-{app_name}")
    return app_group, app_name, bucket, environment, role
Exemple #16
0
def _copy_dist_package(project: Project, logger: Logger, reactor: Reactor,
                       dist_dir: str) -> None:
    dist_file_path = project.expand_path(
        _make_folder(project, "$dir_dist", 'dist'),
        project.get_property("docker_package_dist_file",
                             f"{project.name}-{project.version}.tar.gz"))
    shutil.copy2(dist_file_path, dist_dir)
Exemple #17
0
def _docker_tag_and_push_image(project: Project, logger: Logger,
                               reactor: Reactor, local_img: str) -> None:
    tags = [project.version]
    tag_as_latest = project.get_property("docker_push_tag_as_latest", True)
    if tag_as_latest:
        tags.append('latest')
    for tag in tags:
        remote_img = f"{project.name}:{tag}"
        _exec_cmd(
            project,
            logger,
            reactor,
            'docker',
            'tag',
            local_img,
            remote_img,
            message=f"Tagging local docker image {local_img} - {remote_img}",
            error=f"Error tagging image to remote registry - {remote_img}",
            report_file='docker_push_tag',
            verbose_property="docker_package_verbose_output",
        )
        _exec_cmd(
            project,
            logger,
            reactor,
            'docker',
            'push',
            remote_img,
            message=f"Pushing remote docker image - {remote_img}",
            error=f"Error pushing image to remote registry - {remote_img}",
            report_file="docker_push_tag",
            verbose_property="docker_package_verbose_output",
            force_log=True,
        )
Exemple #18
0
def set_properties(project: Project):
    # Dependencies
    project.depends_on("kombu", "4.0.2")

    project.build_depends_on("sqlalchemy")
    project.build_depends_on("django")
    project.build_depends_on("karellen-sqlite", "~=0.0.0")
    project.build_depends_on("unittest2")

    # Cram Configuration
    project.set_property("cram_fail_if_no_tests", False)

    # Disable flake8
    project.set_property("flake8_break_build", False)

    # Integration Tests Coverage is disabled since there are no integration tests
    project.set_property("unittest_coverage_threshold_warn", 0)
    project.set_property("unittest_coverage_branch_threshold_warn", 0)
    project.set_property("unittest_coverage_branch_partial_threshold_warn", 0)
    project.set_property("unittest_coverage_allow_non_imported_modules", True)
    project.set_property("integrationtest_coverage_threshold_warn", 0)
    project.set_property("integrationtest_coverage_branch_threshold_warn", 0)
    project.set_property(
        "integrationtest_coverage_branch_partial_threshold_warn", 0)
    project.set_property("integrationtest_coverage_allow_non_imported_modules",
                         True)

    project.set_property("pybuilder_header_plugin_break_build", False)

    project.set_property("copy_resources_target", "$dir_dist/karellen")
    project.get_property("copy_resources_glob").append("LICENSE.bsd3")
    project.get_property("copy_resources_glob").append("LICENSE.apache")
    project.include_file("karellen", "LICENSE.bsd3")
    project.include_file("karellen", "LICENSE.apache")

    # Distutils
    project.set_property(
        "distutils_classifiers",
        project.get_property("distutils_classifiers") + [
            'Programming Language :: Python :: 3.3',
            'Programming Language :: Python :: 3.4',
            'Topic :: Software Development :: Libraries',
            'Topic :: Software Development :: Libraries :: Python Modules',
            'Topic :: Internet',
        ])

    project.set_property("pdoc_module_name", "karellen.kombu")
Exemple #19
0
def test_reinitialize_pypi_server_plugin(from_pypirc, mocker):  # pylint: disable=invalid-name,redefined-outer-name
    """ Check reinitialize_pypi_server_plugin function"""
    (pypi_server, pypi_url) = from_pypirc[0]
    project = Project("basedir")
    project.set_property('pypi_server', pypi_server)
    logger_mock = mocker.Mock()
    reinitialize_pypi_server_plugin(project, logger_mock)
    assert project.get_property('distutils_upload_repository') == pypi_server
    assert project.get_property('install_dependencies_index_url') == pypi_url
    logger_mock.warn.assert_called_once_with(
        "Property `pypi_server` defined on initialize stage. "
        "Please use command line `pyb ... -P pypi_server=...`, "
        "otherwise some packages could be downloaded "
        "from default PyPi index.")
    logger_mock.info.assert_called_once_with(
        "Repository `%s` will be used to install_dependencies and "
        "distutils plugins." % pypi_server)
def get_artifact_manager(project: Project) -> ArtifactManager:
    manager_id = project.get_property(ARTIFACT_MANAGER, "S3")
    global artifact_managers
    manager = artifact_managers.get(manager_id)
    if not manager:
        raise BuildFailedException(
            f"Failed to find appropriate artifact manager for {manager_id}")
    return manager
    def test_should_delegate_to_project_get_property_when_attribute_is_not_defined(self):
        project_mock = Project(".")
        project_mock.has_property = Mock(return_value=True)
        project_mock.get_property = Mock(return_value="eggs")

        self.assertEquals("eggs", ProjectDictWrapper(project_mock, Mock())["spam"])

        project_mock.get_property.assert_called_with("spam")
    def test_should_delegate_to_project_get_property_when_attribute_is_not_defined(self):
        project_mock = Project(".")
        project_mock.has_property = Mock(return_value=True)
        project_mock.get_property = Mock(return_value="eggs")

        self.assertEqual("eggs", ProjectDictWrapper(project_mock, Mock())["spam"])

        project_mock.get_property.assert_called_with("spam")
def verify_cypress(project: Project, logger: Logger, reactor: Reactor):
    # Get directories with test and cypress executable
    work_dir = project.expand_path(f"${CYPRESS_TEST_DIR}")
    if _run_cypress_tests_in_directory(work_dir=work_dir,
                                       logger=logger,
                                       project=project,
                                       reactor=reactor):
        package_artifacts(project, work_dir, "cypress",
                          project.get_property(ROLE))
def verify_environment(project: Project, logger: Logger, reactor: Reactor):
    dist_directory = project.get_property(
        WORKING_TEST_DIR, get_working_distribution_directory(project))
    logger.info(f"Preparing to run tests found in: {dist_directory}")
    _run_tests_in_directory(dist_directory, logger, project, reactor)
    artifact_manager = get_artifact_manager(project=project)
    latest_directory = artifact_manager.download_artifacts(project=project,
                                                           logger=logger,
                                                           reactor=reactor)
    _run_tests_in_directory(latest_directory,
                            logger,
                            project,
                            reactor,
                            latest=True)
    if project.get_property(PROMOTE_ARTIFACT, True):
        integration_artifact_push(project=project,
                                  logger=logger,
                                  reactor=reactor)
Exemple #25
0
def _generate_dockerfile(project: Project, logger: Logger, reactor: Reactor,
                         dist_dir: str) -> None:
    dist_file = project.get_property(
        "docker_package_dist_file", f"{project.name}-{project.version}.tar.gz")
    prepare_env_cmd = project.get_property(
        "docker_package_prepare_env_cmd",
        "echo 'empty prepare_env_cmd installing into python'"),
    package_cmd = project.get_property("docker_package_package_cmd",
                                       f"pip install {dist_file}")

    setup_script = os.path.join(dist_dir, "Dockerfile")
    with open(setup_script, "w") as setup_file:
        setup_file.write(
            f"FROM pyb-temp-{project.name}:{project.version}\n"
            f"MAINTAINER {project.get_property('docker_package_image_maintainer', 'anonymous')}\n"
            f"COPY ${dist_file} .\n"
            f"RUN ${prepare_env_cmd}\n"
            f"RUN ${package_cmd}\n")
    os.chmod(setup_script, 0o755)
    def test_should_warn_when_substitution_is_skipped(self):
        project_mock = Project(".")
        logger_mock = Mock()
        project_mock.has_property = Mock(return_value=False)
        project_mock.get_property = Mock()

        self.assertEquals("${n/a}", ProjectDictWrapper(project_mock, logger_mock)["n/a"])

        project_mock.get_property.assert_not_called()
        logger_mock.warn.assert_called_with(
            "Skipping impossible substitution for 'n/a' - there is no matching project attribute or property.")
    def test_should_warn_when_substitution_is_skipped(self):
        project_mock = Project(".")
        logger_mock = Mock()
        project_mock.has_property = Mock(return_value=False)
        project_mock.get_property = Mock()

        self.assertEqual("${n/a}", ProjectDictWrapper(project_mock, logger_mock)["n/a"])

        project_mock.get_property.assert_not_called()
        logger_mock.warn.assert_called_with(
            "Skipping impossible substitution for 'n/a' - there is no matching project attribute or property.")
class SphinxPluginInitializationTests(TestCase):

    def setUp(self):
        self.project = Project("basedir")

    def test_should_leave_user_specified_properties_when_initializing_plugin(self):

        expected_properties = {
            "sphinx_source_dir": "source_dir",
            "sphinx_output_dir": "output_dir",
            "sphinx_config_path": "config_path",
            "sphinx_doc_author": "author",
            "sphinx_doc_builder": "doc_builder",
            "sphinx_project_name": "project_name",
            "sphinx_project_version": "project_version"
        }

        for property_name, property_value in expected_properties.items():
            self.project.set_property(property_name, property_value)

            initialize_sphinx_plugin(self.project)

        for property_name, property_value in expected_properties.items():
            self.assertEquals(

                self.project.get_property(property_name),
                property_value)

    def test_should_set_default_values_when_initializing_plugin(self):
        self.project.authors = [
            Author("John Doe", "*****@*****.**"),
            Author("Jane Doe", "*****@*****.**")]
        initialize_sphinx_plugin(self.project)

        self.project.set_property("sphinx_project_name", "foo")
        self.project.set_property("sphinx_project_version", "1.0")

        self.assertEquals(
            self.project.get_property("sphinx_source_dir"), "docs")
        self.assertEquals(
            self.project.get_property("sphinx_output_dir"), "docs/_build/")
        self.assertEquals(
            self.project.get_property("sphinx_config_path"), "docs")
        self.assertEquals(
            self.project.get_property("sphinx_doc_author"), 'John Doe, Jane Doe')
        self.assertEquals(
            self.project.get_property("sphinx_doc_builder"), "html")
        self.assertEquals(
            self.project.get_property("sphinx_project_name"), "foo")
        self.assertEquals(
            self.project.get_property("sphinx_project_version"), "1.0")
class InitPythonDirectoriesTest(unittest.TestCase):
    def greedy(self, generator):
        return [element for element in generator]

    def setUp(self):
        self.project = Project(".")

    @patch("pybuilder.plugins.python.core_plugin.os.listdir")
    @patch("pybuilder.plugins.python.core_plugin.os.path.isfile")
    def test_should_set_list_modules_function_with_project_modules(
            self, _, source_listdir):
        source_listdir.return_value = ["foo.py", "bar.py", "some-package"]

        init_python_directories(self.project)

        self.assertEquals(['foo', 'bar'],
                          self.greedy(self.project.list_modules()))

    def test_should_set_python_sources_property(self):
        init_python_directories(self.project)
        self.assertEquals(
            "src/main/python",
            self.project.get_property(PYTHON_SOURCES_PROPERTY, "caboom"))

    def test_should_set_scripts_sources_property(self):
        init_python_directories(self.project)
        self.assertEquals(
            "src/main/scripts",
            self.project.get_property(SCRIPTS_SOURCES_PROPERTY, "caboom"))

    def test_should_set_dist_scripts_property(self):
        init_python_directories(self.project)
        self.assertEquals(
            None, self.project.get_property(SCRIPTS_TARGET_PROPERTY, "caboom"))

    def test_should_set_dist_property(self):
        init_python_directories(self.project)
        self.assertEquals(
            "$dir_target/dist/.-1.0-SNAPSHOT",
            self.project.get_property(DISTRIBUTION_PROPERTY, "caboom"))
Exemple #30
0
class SemVerGitPluginInitializationTests(TestCase):
    """ Test initialize_cram_console_scripts    """
    def setUp(self):
        self.project = Project("basedir")

    def test_should_set_default_properties(self):   # pylint: disable=invalid-name
        """ We need to init properties"""
        initialize_semver_git_tag(self.project)
        self.assertEquals(
            self.project.get_property('semver_git_tag_increment_part'), 'patch')
        self.assertEquals(
            self.project.get_property('semver_git_tag_version_prefix'), '')

    def test_should_leave_user_specified_properties(self):  # pylint: disable=invalid-name
        """ We need to keep user-defined properties"""
        self.project.set_property('semver_git_tag_increment_part', 'minor')
        self.project.set_property('semver_git_tag_repo_dir', '/some/dir')
        self.project.set_property('semver_git_tag_changelog',
                                  'dir/CHANGELOG.md')
        self.project.set_property('semver_git_tag_version_prefix', 'v')
        initialize_semver_git_tag(self.project)
        self.assertEquals(
            self.project.get_property('semver_git_tag_increment_part'), 'minor')
        self.assertEquals(
            self.project.get_property('semver_git_tag_repo_dir'), '/some/dir')
        self.assertEquals(
            self.project.get_property('semver_git_tag_changelog'),
            'dir/CHANGELOG.md')
        self.assertEquals(
            self.project.get_property('semver_git_tag_version_prefix'), 'v')
class SphinxPluginInitializationTests(TestCase):
    def setUp(self):
        self.project = Project("basedir")

    def test_should_leave_user_specified_properties_when_initializing_plugin(
            self):

        expected_properties = {
            "sphinx_source_dir": "source_dir",
            "sphinx_output_dir": "output_dir",
            "sphinx_config_path": "config_path",
            "sphinx_doc_author": "author",
            "sphinx_doc_builder": "doc_builder",
            "sphinx_project_name": "project_name",
            "sphinx_project_version": "project_version"
        }

        for property_name, property_value in expected_properties.items():
            self.project.set_property(property_name, property_value)

            initialize_sphinx_plugin(self.project)

        for property_name, property_value in expected_properties.items():
            self.assertEquals(self.project.get_property(property_name),
                              property_value)

    def test_should_set_default_values_when_initializing_plugin(self):
        self.project.authors = [
            Author("John Doe", "*****@*****.**"),
            Author("Jane Doe", "*****@*****.**")
        ]
        initialize_sphinx_plugin(self.project)

        self.project.set_property("sphinx_project_name", "foo")
        self.project.set_property("sphinx_project_version", "1.0")

        self.assertEquals(self.project.get_property("sphinx_source_dir"),
                          "docs")
        self.assertEquals(self.project.get_property("sphinx_output_dir"),
                          "docs/_build/")
        self.assertEquals(self.project.get_property("sphinx_config_path"),
                          "docs")
        self.assertEquals(self.project.get_property("sphinx_doc_author"),
                          'John Doe, Jane Doe')
        self.assertEquals(self.project.get_property("sphinx_doc_builder"),
                          "html")
        self.assertEquals(self.project.get_property("sphinx_project_name"),
                          "foo")
        self.assertEquals(self.project.get_property("sphinx_project_version"),
                          "1.0")
class InitPythonDirectoriesTest (unittest.TestCase):

    def greedy(self, generator):
        return [element for element in generator]

    def setUp(self):
        self.project = Project(".")

    @patch("pybuilder.plugins.python.core_plugin.os.listdir")
    @patch("pybuilder.plugins.python.core_plugin.os.path.isfile")
    def test_should_set_list_modules_function_with_project_modules(self, _, source_listdir):
        source_listdir.return_value = ["foo.py", "bar.py", "some-package"]

        init_python_directories(self.project)

        self.assertEquals(
            ['foo', 'bar'],
            self.greedy(self.project.list_modules())
        )

    def test_should_set_python_sources_property(self):
        init_python_directories(self.project)
        self.assertEquals(
            "src/main/python", self.project.get_property(PYTHON_SOURCES_PROPERTY, "caboom"))

    def test_should_set_scripts_sources_property(self):
        init_python_directories(self.project)
        self.assertEquals(
            "src/main/scripts", self.project.get_property(SCRIPTS_SOURCES_PROPERTY, "caboom"))

    def test_should_set_dist_scripts_property(self):
        init_python_directories(self.project)
        self.assertEquals(
            None, self.project.get_property(SCRIPTS_TARGET_PROPERTY, "caboom"))

    def test_should_set_dist_property(self):
        init_python_directories(self.project)
        self.assertEquals("$dir_target/dist/.-1.0-SNAPSHOT",
                          self.project.get_property(DISTRIBUTION_PROPERTY, "caboom"))
Exemple #33
0
def do_docker_package(project: Project, logger: Logger,
                      reactor: Reactor) -> None:
    project.set_property_if_unset("docker_package_build_dir",
                                  "src/main/docker")
    project.set_property_if_unset("docker_package_build_image", project.name)
    project.set_property_if_unset("docker_package_build_version",
                                  project.version)
    project.set_property_if_unset("docker_package_verbose_output",
                                  project.get_property("verbose"))

    reactor.pybuilder_venv.verify_can_execute(
        command_and_arguments=["docker", "--version"],
        prerequisite="docker",
        caller="docker_package")

    dist_dir = _make_folder(project, "$dir_dist", "docker")
    build_img = project.get_property("docker_package_build_img",
                                     f"{project.name}:{project.version}")
    _docker_build_stages(project, logger, reactor, dist_dir, build_img)
    logger.info(
        f"Finished build docker image - {build_img} - with dist file - {dist_dir}"
    )
Exemple #34
0
def set_properties(project: Project):
    project.depends_on("pybuilder")

    project.set_property('flake8_break_build', True)
    project.set_property('flake8_include_test_sources', True)
    project.set_property('flake8_include_scripts', True)
    project.set_property('flake8_max_line_length', 130)

    project.set_property("copy_resources_target", "$dir_dist/pybuilder-pipenv")
    project.get_property("copy_resources_glob").append("LICENSE")
    project.include_file("pybuilder-pipenv", "LICENSE")

    project.set_property("distutils_classifiers", [
        'Programming Language :: Python',
        'Programming Language :: Python :: Implementation :: CPython',
        'Programming Language :: Python :: Implementation :: PyPy',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.5',
        'Programming Language :: Python :: 3.6',
        'Programming Language :: Python :: 3.7',
        'Development Status :: 4 - Beta', 'Intended Audience :: Developers',
        'License :: OSI Approved :: GNU General Public License (GPL)',
        'Topic :: Software Development :: Build Tools'
    ])
Exemple #35
0
class InitPythonDirectoriesTest (unittest.TestCase):

    def setUp(self):
        self.project = Project(".")

    def test_should_set_python_sources_property(self):
        init_python_directories(self.project)
        self.assertEquals(
            "src/main/python", self.project.get_property(PYTHON_SOURCES_PROPERTY, "caboom"))

    def test_should_set_scripts_sources_property(self):
        init_python_directories(self.project)
        self.assertEquals(
            "src/main/scripts", self.project.get_property(SCRIPTS_SOURCES_PROPERTY, "caboom"))

    def test_should_set_dist_scripts_property(self):
        init_python_directories(self.project)
        self.assertEquals(
            None, self.project.get_property(SCRIPTS_TARGET_PROPERTY, "caboom"))

    def test_should_set_dist_property(self):
        init_python_directories(self.project)
        self.assertEquals("$dir_target/dist/.-1.0-SNAPSHOT",
                          self.project.get_property(DISTRIBUTION_PROPERTY, "caboom"))
Exemple #36
0
def set_properties(project: Project):
    # Cram Configuration
    project.set_property("cram_fail_if_no_tests", False)

    # Integration Tests Coverage is disabled since there are no integration tests
    project.set_property("integrationtest_coverage_threshold_warn", 0)
    project.set_property("integrationtest_coverage_branch_threshold_warn", 0)
    project.set_property("integrationtest_coverage_branch_partial_threshold_warn", 0)

    # Distutils
    project.set_property("distutils_classifiers", project.get_property("distutils_classifiers") + [
        'Topic :: Software Development :: Libraries',
        'Topic :: Software Development :: Libraries :: Python Modules',
        'Topic :: Software Development :: Testing'])

    project.set_property("pdoc_module_name", "karellen.testing")
class RonnPluginInitializationTests(TestCase):
    def setUp(self):
        self.project = Project("basedir")

    def test_should_leave_user_specified_properties_when_initializing_plugin(
            self):

        expected_properties = {
            "dir_manpages": "foo",
            "manpage_source": "bar",
            "manpage_section": 1
        }

        for property_name, property_value in expected_properties.items():
            self.project.set_property(property_name, property_value)

            init_ronn_manpage_plugin(self.project)

        for property_name, property_value in expected_properties.items():
            self.assertEquals(self.project.get_property(property_name),
                              property_value)

    @patch('pybuilder.plugins.ronn_manpage_plugin.assert_can_execute')
    def test_should_check_that_ronn_is_executable(self,
                                                  mock_assert_can_execute):

        mock_logger = Mock(Logger)

        assert_ronn_is_executable(mock_logger)
        mock_assert_can_execute.assert_called_with(
            caller='plugin ronn_manpage_plugin',
            command_and_arguments=['ronn', '--version'],
            prerequisite='ronn')

    @patch('pybuilder.plugins.ronn_manpage_plugin.assert_can_execute')
    def test_should_check_that_gzip_is_executable(self,
                                                  mock_assert_can_execute):

        mock_logger = Mock(Logger)

        assert_gzip_is_executable(mock_logger)
        mock_assert_can_execute.assert_called_with(
            caller="plugin ronn_manpage_plugin",
            command_and_arguments=["gzip", "--version"],
            prerequisite="gzip")
class RonnPluginInitializationTests(TestCase):

    def setUp(self):
        self.project = Project("basedir")

    def test_should_leave_user_specified_properties_when_initializing_plugin(self):

        expected_properties = {
            "dir_manpages": "foo",
            "manpage_source": "bar",
            "manpage_section": 1
        }

        for property_name, property_value in expected_properties.items():
            self.project.set_property(property_name, property_value)

            init_ronn_manpage_plugin(self.project)

        for property_name, property_value in expected_properties.items():
            self.assertEquals(

                self.project.get_property(property_name),
                property_value)

    @patch('pybuilder.plugins.ronn_manpage_plugin.assert_can_execute')
    def test_should_check_that_ronn_is_executable(self, mock_assert_can_execute):

        mock_logger = Mock(Logger)

        assert_ronn_is_executable(mock_logger)
        mock_assert_can_execute.assert_called_with(
            caller='plugin ronn_manpage_plugin',
            command_and_arguments=['ronn', '--version'],
            prerequisite='ronn')

    @patch('pybuilder.plugins.ronn_manpage_plugin.assert_can_execute')
    def test_should_check_that_gzip_is_executable(self, mock_assert_can_execute):

        mock_logger = Mock(Logger)

        assert_gzip_is_executable(mock_logger)
        mock_assert_can_execute.assert_called_with(
            caller="plugin ronn_manpage_plugin",
            command_and_arguments=["gzip", "--version"],
            prerequisite="gzip")
class UtilsTest(unittest.TestCase):
    def setUp(self):
        self.project = Project('/path/to/project')
        self.project.set_property('dir_source_unittest_python',
                                  'src/unittest/python')
        self.project.set_property('dir_target', 'target')

    def test_importDirs(self):
        cwd = os.getcwd()

        dirs = utils.getImportantDirs(self.project)

        # test_dir
        self.assertEquals(
            dirs[0], cwd + "/" +
            self.project.get_property('dir_source_unittest_python'))

        # log_dir
        self.assertEquals(dirs[1], cwd + "/target/allure_report_logs")
 def upload(self, file: str, project: Project, logger: Logger,
            reactor: Reactor):
     if project.get_property("abort_upload", "false") != "false":
         return
     # First make sure bucket exists
     self.create_bucket(logger, project, reactor)
     relative_path = get_latest_artifact_destination(logger, project)
     self._s3_transfer(file,
                       relative_path,
                       project,
                       reactor,
                       logger,
                       recursive=False)
     relative_path = get_versioned_artifact_destination(logger, project)
     self._s3_transfer(file,
                       relative_path,
                       project,
                       reactor,
                       logger,
                       recursive=False)
class RonnPluginInitializationTests(TestCase):
    def setUp(self):
        self.project = Project("basedir")
        self.logger = Mock(Logger)
        self.reactor = Mock()
        self.pyb_env = pyb_env = Mock()
        self.reactor.python_env_registry = {"pybuilder": pyb_env}
        self.reactor.pybuilder_venv = pyb_env

    def test_should_leave_user_specified_properties_when_initializing_plugin(
            self):

        expected_properties = {
            "dir_manpages": "foo",
            "manpage_source": "bar",
            "manpage_section": 1
        }

        for property_name, property_value in expected_properties.items():
            self.project.set_property(property_name, property_value)

            init_ronn_manpage_plugin(self.project)

        for property_name, property_value in expected_properties.items():
            self.assertEqual(self.project.get_property(property_name),
                             property_value)

    def test_should_check_that_ronn_is_executable(self):
        assert_ronn_is_executable(self.project, self.logger, self.reactor)
        self.pyb_env.verify_can_execute.assert_called_with(
            caller='plugin ronn_manpage_plugin',
            command_and_arguments=['ronn', '--version'],
            prerequisite='ronn')

    def test_should_check_that_gzip_is_executable(self):
        assert_gzip_is_executable(self.project, self.logger, self.reactor)
        self.pyb_env.verify_can_execute.assert_called_with(
            caller="plugin ronn_manpage_plugin",
            command_and_arguments=["gzip", "--version"],
            prerequisite="gzip")
Exemple #42
0
class ProjectTest (unittest.TestCase):

    def setUp(self):
        self.project = Project(basedir="/imaginary", name="Unittest")

    def test_should_pick_directory_name_for_project_name_when_name_is_not_given(self):
        try:
            when(os.path).basename("/imaginary").thenReturn("imaginary")

            project = Project(basedir="/imaginary")

            self.assertEquals("imaginary", project.name)
            verify(os.path).basename("/imaginary")
        finally:
            unstub()

    def test_get_property_should_return_default_value_when_property_is_not_set(self):
        self.assertEquals("spam", self.project.get_property("spam", "spam"))

    def test_get_property_should_return_property_value_when_property_is_set(self):
        self.project.set_property("spam", "eggs")
        self.assertEquals("eggs", self.project.get_property("spam", "spam"))

    def test_has_property_should_return_false_when_property_is_not_set(self):
        self.assertFalse(self.project.has_property("spam"))

    def test_has_property_should_return_true_when_property_is_set(self):
        self.project.set_property("spam", "eggs")
        self.assertTrue(self.project.has_property("spam"))

    def test_set_property_if_unset_should_set_property_when_property_is_not_set(self):
        self.project.set_property_if_unset("spam", "spam")
        self.assertEquals("spam", self.project.get_property("spam"))

    def test_set_property_if_unset_should_not_set_property_when_property_is_already_set(self):
        self.project.set_property("spam", "eggs")
        self.project.set_property_if_unset("spam", "spam")
        self.assertEquals("eggs", self.project.get_property("spam"))

    def test_expand_should_raise_exception_when_property_is_not_set(self):
        self.assertRaises(
            MissingPropertyException, self.project.expand, "$spam")

    def test_expand_should_return_expanded_string_when_property_is_set(self):
        self.project.set_property("spam", "eggs")
        self.assertEquals("eggs", self.project.expand("$spam"))

    def test_expand_should_return_expanded_string_when_two_properties_are_found_and_set(self):
        self.project.set_property("spam", "spam")
        self.project.set_property("eggs", "eggs")
        self.assertEquals(
            "spam and eggs", self.project.expand("$spam and $eggs"))

    def test_expand_should_expand_property_with_value_being_an_property_expression(self):
        self.project.set_property("spam", "spam")
        self.project.set_property("eggs", "$spam")
        self.assertEquals("spam", self.project.expand("$eggs"))

    def test_expand_should_raise_exception_when_first_expansion_leads_to_property_reference_and_property_is_undefined(self):
        self.project.set_property("eggs", "$spam")
        self.assertRaises(
            MissingPropertyException, self.project.expand, "$eggs")

    def test_expand_path_should_return_expanded_path(self):
        self.project.set_property("spam", "spam")
        self.project.set_property("eggs", "eggs")
        self.assertEquals(os.path.join("/imaginary", "spam", "eggs"),
                          self.project.expand_path("$spam/$eggs"))

    def test_expand_path_should_return_expanded_path_and_additional_parts_when_additional_parts_are_given(self):
        self.project.set_property("spam", "spam")
        self.project.set_property("eggs", "eggs")
        self.assertEquals(
            os.path.join("/imaginary", "spam", "eggs", "foo", "bar"),
            self.project.expand_path("$spam/$eggs", "foo", "bar"))

    def test_should_raise_exception_when_getting_mandatory_propert_and_property_is_not_found(self):
        self.assertRaises(MissingPropertyException,
                          self.project.get_mandatory_property, "i_dont_exist")

    def test_should_return_property_value_when_getting_mandatory_propert_and_property_exists(self):
        self.project.set_property("spam", "spam")
        self.assertEquals("spam", self.project.get_mandatory_property("spam"))

    def test_should_add_runtime_dependency_with_name_only(self):
        self.project.depends_on("spam")
        self.assertEquals(1, len(self.project.dependencies))
        self.assertEquals("spam", self.project.dependencies[0].name)
        self.assertEquals(None, self.project.dependencies[0].version)

    def test_should_add_dependency_with_name_and_version(self):
        self.project.depends_on("spam", "0.7")
        self.assertEquals(1, len(self.project.dependencies))
        self.assertEquals("spam", self.project.dependencies[0].name)
        self.assertEquals("0.7", self.project.dependencies[0].version)

    def test_should_add_dependency_with_name_and_version_only_once(self):
        self.project.depends_on("spam", "0.7")
        self.project.depends_on("spam", "0.7")
        self.assertEquals(1, len(self.project.dependencies))
        self.assertEquals("spam", self.project.dependencies[0].name)
        self.assertEquals("0.7", self.project.dependencies[0].version)
class InstallDependenciesTest(unittest.TestCase):
    def setUp(self):
        self.project = Project(".")

    def test_should_leave_user_specified_properties_when_initializing_plugin(self):

        expected_properties = {
            "distutils_commands": ["foo", "bar"],
            "distutils_issue8876_workaround_enabled": True,
            "distutils_classifiers": [
                "Development Status :: 3 - Beta",
                "Programming Language :: Rust"
            ],
            "distutils_use_setuptools": False
        }

        for property_name, property_value in expected_properties.items():
            self.project.set_property(property_name, property_value)

            initialize_distutils_plugin(self.project)

        for property_name, property_value in expected_properties.items():
            self.assertEquals(
                self.project.get_property("distutils_commands"), ["foo", "bar"])
            self.assertEquals(
                self.project.get_property("distutils_issue8876_workaround_enabled"), True)
            self.assertEquals(
                self.project.get_property("distutils_classifiers"), ["Development Status :: 3 - Beta",
                                                                     "Programming Language :: Rust"])
            self.assertEquals(
                self.project.get_property("distutils_use_setuptools"), False)

    def test_should_return_empty_string_when_no_dependency_is_given(self):
        self.assertEqual("[]", build_install_dependencies_string(self.project))

    def test_should_return_single_dependency_string(self):
        self.project.depends_on("spam")
        self.assertEqual(
            "['spam']", build_install_dependencies_string(self.project))

    def test_should_return_single_dependency_string_with_version(self):
        self.project.depends_on("spam", "0.7")
        self.assertEqual(
            "['spam>=0.7']", build_install_dependencies_string(self.project))

    def test_should_return_multiple_dependencies_string_with_versions(self):
        self.project.depends_on("spam", "0.7")
        self.project.depends_on("eggs")
        self.assertEqual(
            "[\n            'eggs',\n            'spam>=0.7'\n        ]",
            build_install_dependencies_string(self.project))

    def test_should_not_insert_url_dependency_into_install_requires(self):
        self.project.depends_on("spam")
        self.project.depends_on(
            "pyassert", url="https://github.com/downloads/halimath/pyassert/pyassert-0.2.2.tar.gz")

        self.assertEqual(
            "['spam']", build_install_dependencies_string(self.project))

    def test_should_not_insert_default_version_operator_when_project_contains_operator_in_version(self):
        self.project.depends_on("spam", "==0.7")
        self.assertEqual(
            "['spam==0.7']", build_install_dependencies_string(self.project))

    @patch("pybuilder.plugins.python.distutils_plugin.open", create=True)
    def test_should_quote_requirements(self, mock_open):
        mock_open.return_value = MagicMock(spec=TYPE_FILE)
        handle = mock_open.return_value.__enter__.return_value
        handle.readlines.return_value = ["foo", "bar"]
        self.project.depends_on_requirements("requirements.txt")

        self.assertEqual(
            "[\n            'foo',\n            'bar'\n        ]", build_install_dependencies_string(self.project))

    @patch("pybuilder.plugins.python.distutils_plugin.open", create=True)
    def test_should_ignore_empty_requirement_lines(self, mock_open):
        mock_open.return_value = MagicMock(spec=TYPE_FILE)
        handle = mock_open.return_value.__enter__.return_value
        handle.readlines.return_value = ["", "foo", "bar"]
        self.project.depends_on_requirements("requirements.txt")

        self.assertEqual(
            "[\n            'foo',\n            'bar'\n        ]", build_install_dependencies_string(self.project))

    @patch("pybuilder.plugins.python.distutils_plugin.open", create=True)
    def test_should_ignore_comments_from_requirements(self, mock_open):
        mock_open.return_value = MagicMock(spec=TYPE_FILE)
        handle = mock_open.return_value.__enter__.return_value
        handle.readlines.return_value = ["#comment", "bar"]
        self.project.depends_on_requirements("requirements.txt")

        self.assertEqual(
            "['bar']", build_install_dependencies_string(self.project))

    @patch("pybuilder.plugins.python.distutils_plugin.open", create=True)
    def test_should_ignore_comments_with_leading_space_from_requirements(self, mock_open):
        mock_open.return_value = MagicMock(spec=TYPE_FILE)
        handle = mock_open.return_value.__enter__.return_value
        handle.readlines.return_value = [" # comment", "bar"]
        self.project.depends_on_requirements("requirements.txt")

        self.assertEqual(
            "['bar']", build_install_dependencies_string(self.project))

    @patch("pybuilder.plugins.python.distutils_plugin.open", create=True)
    def test_should_ignore_editable_urls_from_requirements(self, mock_open):
        mock_open.return_value = MagicMock(spec=TYPE_FILE)
        handle = mock_open.return_value.__enter__.return_value
        handle.readlines.return_value = [
            "foo", "-e git+https://github.com/someuser/someproject.git#egg=some_package"]
        self.project.depends_on_requirements("requirements.txt")

        self.assertEqual(
            "['foo']", build_install_dependencies_string(self.project))

    @patch("pybuilder.plugins.python.distutils_plugin.open", create=True)
    def test_should_ignore_expanded_editable_urls_from_requirements(self, mock_open):
        mock_open.return_value = MagicMock(spec=TYPE_FILE)
        handle = mock_open.return_value.__enter__.return_value
        handle.readlines.return_value = [
            "foo", "--editable git+https://github.com/someuser/someproject.git#egg=some_package"]
        self.project.depends_on_requirements("requirements.txt")

        self.assertEqual(
            "['foo']", build_install_dependencies_string(self.project))
class TaskPoolProgressTests(unittest.TestCase):

    def setUp(self):
        self.progress = TaskPoolProgress(42, 8)
        self.project = Project("basedir")

    def test_should_leave_user_specified_properties_when_initializing_plugin(self):

        expected_properties = {
            "dir_source_integrationtest_python": "foo/bar/python",
            "integrationtest_file_glob": "*foo.py",
            "integrationtest_file_suffix": True,
            "integrationtest_additional_environment": {"env3": "foo"},
            "integrationtest_inherit_environment": True,
            "integrationtest_always_verbose": True
            }
        for property_name, property_value in expected_properties.items():
            self.project.set_property(property_name, property_value)

            initialize_integrationtest_plugin(self.project)

        for property_name, property_value in expected_properties.items():
            self.assertEqual(
                self.project.get_property("dir_source_integrationtest_python"), "foo/bar/python")
            self.assertEqual(
                self.project.get_property("integrationtest_file_glob"), "*foo.py")
            self.assertEqual(
                self.project.get_property("integrationtest_file_suffix"), True)
            self.assertEqual(
                self.project.get_property("integrationtest_additional_environment"), {"env3": "foo"}),
            self.assertEqual(
                self.project.get_property("integrationtest_always_verbose"), True)

    def test_should_create_new_progress(self):
        self.assertEqual(self.progress.workers_count, 8)
        self.assertEqual(self.progress.finished_tasks_count, 0)
        self.assertEqual(self.progress.total_tasks_count, 42)

    def test_should_have_max_amount_of_tasks_running_when_limited_by_workers(self):
        self.assertEqual(self.progress.running_tasks_count, 8)

    def test_should_have_max_amount_of_tasks_running_when_limited_by_tasks(self):
        progress = TaskPoolProgress(2, 4)

        self.assertEqual(progress.running_tasks_count, 2)

    def test_should_have_max_amount_of_tasks_running_when_limited_by_tasks_after_updating(self):
        self.progress.update(40)

        self.assertEqual(self.progress.running_tasks_count, 2)

    def test_should_have_tasks_that_are_neither_running_nor_finished_as_waiting(self):
        self.assertEqual(self.progress.waiting_tasks_count, 42 - 8)

    def test_should_have_tasks_that_are_neither_running_nor_finished_as_waiting_after_updating(self):
        self.progress.update(2)

        self.assertEqual(self.progress.waiting_tasks_count, 40 - 8)

    def test_should_not_be_finished_when_tasks_are_still_todo(self):
        self.assertFalse(self.progress.is_finished)

    def test_should_not_be_finished_when_tasks_are_still_running(self):
        progress = TaskPoolProgress(1, 1)

        self.assertFalse(progress.is_finished)

    def test_should_be_finished_when_all_tasks_are_finished(self):
        progress = TaskPoolProgress(1, 1)
        progress.update(1)

        self.assertTrue(progress.is_finished)

    @patch('pybuilder.plugins.python.integrationtest_plugin.sys.stdout')
    def test_should_be_displayed_when_tty_given(self, stdout):
        stdout.isatty.return_value = True

        self.assertTrue(self.progress.can_be_displayed)

    @patch('pybuilder.plugins.python.integrationtest_plugin.sys.stdout')
    def test_should_not_be_displayed_when_no_tty_given(self, stdout):
        stdout.isatty.return_value = False

        self.assertFalse(self.progress.can_be_displayed)

    @patch('pybuilder.plugins.python.integrationtest_plugin.styled_text')
    def test_should_render_progress(self, styled):
        styled.side_effect = lambda text, *styles: text
        progress = TaskPoolProgress(8, 2)
        progress.update(3)

        self.assertEqual(progress.render(),
                         '[---ᗧ//|||]')

    @patch('pybuilder.plugins.python.integrationtest_plugin.styled_text')
    def test_should_not_render_pacman_when_finished(self, styled):
        styled.side_effect = lambda text, *styles: text
        progress = TaskPoolProgress(8, 2)
        progress.update(8)

        self.assertEqual(progress.render(),
                         '[--------] ')

    @patch('pybuilder.plugins.python.integrationtest_plugin.styled_text')
    @patch('pybuilder.plugins.python.integrationtest_plugin.print_text')
    @patch('pybuilder.plugins.python.integrationtest_plugin.TaskPoolProgress.can_be_displayed')
    def test_should_erase_previous_progress_on_subsequent_renders(self, _, print_text, styled):
        styled.side_effect = lambda text, *styles: text
        progress = TaskPoolProgress(8, 2)
        progress.update(2)

        progress.render_to_terminal()
        print_text.assert_called_with('[--ᗧ//||||]', flush=True)
        progress.render_to_terminal()
        print_text.assert_called_with(
            '\b' * (10 + len('ᗧ')) + '[--ᗧ//||||]', flush=True)
class InitPythonDirectoriesTest (unittest.TestCase):

    def greedy(self, generator):
        return [element for element in generator]

    def setUp(self):
        self.project = Project(".")

    @patch("pybuilder.plugins.python.core_plugin.os.listdir")
    @patch("pybuilder.plugins.python.core_plugin.os.path.isfile")
    def test_should_set_list_modules_function_with_project_modules(self, _, source_listdir):
        source_listdir.return_value = ["foo.py", "bar.py", "some-package"]

        init_python_directories(self.project)

        self.assertEquals(
            ['foo', 'bar'],
            self.greedy(self.project.list_modules())
        )

    @patch("pybuilder.plugins.python.core_plugin.os.walk")
    @patch("pybuilder.plugins.python.core_plugin.os.path.exists")
    def test_should_set_list_packages_function_with_project_packages(self, _, walk):
        walk.return_value = [("./src/main/python/pybuilder",
                              ['pluginhelper', 'plugins'],
                              ['execution.py', 'terminal.py', 'execution.pyc', 'scaffolding.py']
                              )]
        self.project.set_property("dir_source_main_python",
                                  "src/main/python")

        init_python_directories(self.project)

        self.assertEquals(
            ['pybuilder.pluginhelper',
             'pybuilder.plugins'],
            self.greedy(self.project.list_packages())
        )

    @patch("pybuilder.plugins.python.core_plugin.os.walk")
    @patch("pybuilder.plugins.python.core_plugin.os.path.exists")
    def test_should_not_cut_off_packages_when_path_ends_with_trailing_slash(self, _, walk):
        walk.return_value = [("./src/main/python/pybuilder",
                              ['pluginhelper', 'plugins'],
                              ['execution.py', 'terminal.py', 'execution.pyc', 'scaffolding.py']
                              )]
        self.project.set_property("dir_source_main_python",
                                  "src/main/python/")

        init_python_directories(self.project)

        self.assertEquals(
            ['pybuilder.pluginhelper',
             'pybuilder.plugins'],
            self.greedy(self.project.list_packages())
        )

    def test_should_set_python_sources_property(self):
        init_python_directories(self.project)
        self.assertEquals(
            "src/main/python", self.project.get_property(PYTHON_SOURCES_PROPERTY, "caboom"))

    def test_should_set_scripts_sources_property(self):
        init_python_directories(self.project)
        self.assertEquals(
            "src/main/scripts", self.project.get_property(SCRIPTS_SOURCES_PROPERTY, "caboom"))

    def test_should_set_dist_scripts_property(self):
        init_python_directories(self.project)
        self.assertEquals(
            None, self.project.get_property(SCRIPTS_TARGET_PROPERTY, "caboom"))

    def test_should_set_dist_property(self):
        init_python_directories(self.project)
        self.assertEquals("$dir_target/dist/.-1.0-SNAPSHOT",
                          self.project.get_property(DISTRIBUTION_PROPERTY, "caboom"))
Exemple #46
0
class Reactor(object):
    _current_instance = None

    @staticmethod
    def current_instance():
        return Reactor._current_instance

    @staticmethod
    def _set_current_instance(reactor):
        Reactor._current_instance = reactor

    def __init__(self, logger, execution_manager, plugin_loader=None):
        self.logger = logger
        self.execution_manager = execution_manager
        if not plugin_loader:
            self.plugin_loader = DispatchingPluginLoader(self.logger,
                                                         BuiltinPluginLoader(self.logger),
                                                         DownloadingPluginLoader(self.logger))
        else:
            self.plugin_loader = plugin_loader
        self._plugins = []
        self.project = None

    def require_plugin(self, plugin, version=None, plugin_module_name=None):
        if plugin not in self._plugins:
            try:
                self._plugins.append(plugin)
                self.import_plugin(plugin, version, plugin_module_name)
            except:  # NOQA
                self._plugins.remove(plugin)
                raise

    def get_plugins(self):
        return self._plugins

    def get_tasks(self):
        return self.execution_manager.tasks

    def validate_project(self):
        validation_messages = self.project.validate()
        if len(validation_messages) > 0:
            raise ProjectValidationFailedException(validation_messages)

    def prepare_build(self,
                      property_overrides=None,
                      project_directory=".",
                      project_descriptor="build.py",
                      exclude_optional_tasks=None,
                      exclude_tasks=None,
                      exclude_all_optional=False):
        if not property_overrides:
            property_overrides = {}
        Reactor._set_current_instance(self)

        project_directory, project_descriptor = self.verify_project_directory(
            project_directory, project_descriptor)

        self.logger.debug("Loading project module from %s", project_descriptor)

        self.project = Project(basedir=project_directory)

        self.project_module = self.load_project_module(project_descriptor)

        self.apply_project_attributes()
        self.override_properties(property_overrides)

        self.logger.debug("Have loaded plugins %s", ", ".join(self._plugins))

        self.collect_tasks_and_actions_and_initializers(self.project_module)

        self.execution_manager.resolve_dependencies(exclude_optional_tasks, exclude_tasks, exclude_all_optional)

    def build(self, tasks=None, environments=None):
        if not tasks:
            tasks = []
        else:
            tasks = as_list(tasks)
        if not environments:
            environments = []

        execution_plan = self.create_execution_plan(tasks, environments)
        return self.build_execution_plan(tasks, execution_plan)

    def create_execution_plan(self, tasks, environments):
        Reactor._set_current_instance(self)

        if environments:
            self.logger.info(
                "Activated environments: %s", ", ".join(environments))

        self.execution_manager.execute_initializers(
            environments, logger=self.logger, project=self.project)

        self.log_project_properties()

        self.validate_project()

        if not len(tasks):
            if self.project.default_task:
                tasks += as_list(self.project.default_task)
            else:
                raise PyBuilderException("No default task given.")

        return self.execution_manager.build_execution_plan(tasks)

    def build_execution_plan(self, tasks, execution_plan):
        self.logger.debug("Execution plan is %s", ", ".join(
            [task.name for task in execution_plan]))

        self.logger.info(
            "Building %s version %s%s", self.project.name, self.project.version, get_dist_version_string(self.project))
        self.logger.info("Executing build in %s", self.project.basedir)

        if len(tasks) == 1:
            self.logger.info("Going to execute task %s", tasks[0])
        else:
            list_of_tasks = ", ".join(tasks)
            self.logger.info("Going to execute tasks: %s", list_of_tasks)

        task_execution_summaries = self.execution_manager.execute_execution_plan(
            execution_plan,
            logger=self.logger,
            project=self.project,
            reactor=self)

        return BuildSummary(self.project, task_execution_summaries)

    def execute_task(self, task_name):
        execution_plan = self.execution_manager.build_execution_plan(task_name)

        self.execution_manager.execute_execution_plan(execution_plan,
                                                      logger=self.logger,
                                                      project=self.project,
                                                      reactor=self)

    def execute_task_shortest_plan(self, task_name):
        execution_plan = self.execution_manager.build_shortest_execution_plan(task_name)

        self.execution_manager.execute_execution_plan(execution_plan,
                                                      logger=self.logger,
                                                      project=self.project,
                                                      reactor=self)

    def override_properties(self, property_overrides):
        for property_override in property_overrides:
            self.project.set_property(
                property_override, property_overrides[property_override])

    def log_project_properties(self):
        formatted = ""
        for key in sorted(self.project.properties):
            formatted += "\n%40s : %s" % (key, self.project.get_property(key))
        self.logger.debug("Project properties: %s", formatted)

    def import_plugin(self, plugin, version=None, plugin_module_name=None):
        self.logger.debug("Loading plugin '%s'%s", plugin, " version %s" % version if version else "")
        plugin_module = self.plugin_loader.load_plugin(self.project, plugin, version, plugin_module_name)
        self.collect_tasks_and_actions_and_initializers(plugin_module)

    def collect_tasks_and_actions_and_initializers(self, project_module):
        injected_task_dependencies = {}

        def normalize_candidate_name(candidate):
            return getattr(candidate, NAME_ATTRIBUTE, candidate.__name__ if hasattr(candidate, "__name__") else None)

        def add_task_dependency(names, depends_on, optional):
            for name in as_list(names):
                if not isinstance(name, basestring):
                    name = normalize_candidate_name(name)
                if name not in injected_task_dependencies:
                    injected_task_dependencies[name] = list()
                injected_task_dependencies[name].append(TaskDependency(depends_on, optional))

        for name in dir(project_module):
            candidate = getattr(project_module, name)
            name = normalize_candidate_name(candidate)

            if getattr(candidate, TASK_ATTRIBUTE, None):
                dependents = getattr(candidate, DEPENDENTS_ATTRIBUTE, None)

                if dependents:
                    dependents = list(as_list(dependents))
                    for d in dependents:
                        if isinstance(d, optional):
                            d = d()
                            add_task_dependency(d, name, True)
                        else:
                            add_task_dependency(d, name, False)

        for name in dir(project_module):
            candidate = getattr(project_module, name)
            name = normalize_candidate_name(candidate)

            description = getattr(candidate, DESCRIPTION_ATTRIBUTE, "")

            if getattr(candidate, TASK_ATTRIBUTE, None):
                dependencies = getattr(candidate, DEPENDS_ATTRIBUTE, None)

                task_dependencies = list()
                if dependencies:
                    dependencies = list(as_list(dependencies))
                    for d in dependencies:
                        if isinstance(d, optional):
                            d = as_list(d())
                            task_dependencies.extend([TaskDependency(item, True) for item in d])
                        else:
                            task_dependencies.append(TaskDependency(d))

                # Add injected
                if name in injected_task_dependencies:
                    task_dependencies.extend(injected_task_dependencies[name])
                    del injected_task_dependencies[name]

                self.logger.debug("Found task '%s' with dependencies %s", name, task_dependencies)
                self.execution_manager.register_task(
                    Task(name, candidate, task_dependencies, description))

            elif getattr(candidate, ACTION_ATTRIBUTE, None):
                before = getattr(candidate, BEFORE_ATTRIBUTE, None)
                after = getattr(candidate, AFTER_ATTRIBUTE, None)

                only_once = getattr(candidate, ONLY_ONCE_ATTRIBUTE, False)
                teardown = getattr(candidate, TEARDOWN_ATTRIBUTE, False)

                self.logger.debug("Found action %s", name)
                self.execution_manager.register_action(
                    Action(name, candidate, before, after, description, only_once, teardown))

            elif getattr(candidate, INITIALIZER_ATTRIBUTE, None):
                environments = getattr(candidate, ENVIRONMENTS_ATTRIBUTE, [])

                self.execution_manager.register_initializer(
                    Initializer(name, candidate, environments, description))

        self.execution_manager.register_late_task_dependencies(injected_task_dependencies)

    def apply_project_attributes(self):
        self.propagate_property("name")
        self.propagate_property("version")
        self.propagate_property("default_task")
        self.propagate_property("summary")
        self.propagate_property("home_page")
        self.propagate_property("description")
        self.propagate_property("authors")
        self.propagate_property("license")
        self.propagate_property("url")

    def propagate_property(self, property):
        if hasattr(self.project_module, property):
            value = getattr(self.project_module, property)
            setattr(self.project, property, value)

    @staticmethod
    def load_project_module(project_descriptor):
        try:
            return imp.load_source("build", project_descriptor)
        except ImportError as e:
            raise PyBuilderException(
                "Error importing project descriptor %s: %s" % (project_descriptor, e))

    @staticmethod
    def verify_project_directory(project_directory, project_descriptor):
        project_directory = os.path.abspath(project_directory)

        if not os.path.exists(project_directory):
            raise PyBuilderException(
                "Project directory does not exist: %s", project_directory)

        if not os.path.isdir(project_directory):
            raise PyBuilderException(
                "Project directory is not a directory: %s", project_directory)

        project_descriptor_full_path = os.path.join(
            project_directory, project_descriptor)

        if not os.path.exists(project_descriptor_full_path):
            raise PyBuilderException(
                "Project directory does not contain descriptor file: %s",
                project_descriptor_full_path)

        if not os.path.isfile(project_descriptor_full_path):
            raise PyBuilderException(
                "Project descriptor is not a file: %s", project_descriptor_full_path)

        return project_directory, project_descriptor_full_path
class CoveragePluginTests(TestCase):
    def setUp(self):
        self.project = Project("basedir")

    def test_should_leave_user_specified_properties_when_initializing_plugin(self):

        expected_properties = {
            "coverage_threshold_warn": 120,
            "coverage_branch_threshold_warn": 120,
            "coverage_branch_partial_threshold_warn": 120,
            "coverage_break_build": False,
            "coverage_reload_modules": False,
            "coverage_exceptions": ["foo"],
            "coverage_fork": True
        }

        for property_name, property_value in expected_properties.items():
            self.project.set_property(property_name, property_value)

            init_coverage_properties(self.project)

        for property_name, property_value in expected_properties.items():
            self.assertEquals(
                self.project.get_property("coverage_threshold_warn"), 120)
            self.assertEquals(
                self.project.get_property("coverage_branch_threshold_warn"), 120)
            self.assertEquals(
                self.project.get_property("coverage_branch_partial_threshold_warn"), 120)
            self.assertEquals(
                self.project.get_property("coverage_break_build"), False)
            self.assertEquals(
                self.project.get_property("coverage_reload_modules"), False)
            self.assertEquals(
                self.project.get_property("coverage_exceptions"), ["foo"])
            self.assertEquals(
                self.project.get_property("coverage_fork"), True)

    def test_list_all_covered_modules_all_loaded(self):
        module_a_val = MagicMock()
        module_b_val = MagicMock()
        with patch.dict('sys.modules', module_a=module_a_val, module_b=module_b_val):
            with patch(import_patch) as import_func:
                returned_modules = _list_all_covered_modules(MagicMock(), ['module_a', 'module_b'], [])

        self.assertEquals([module_a_val, module_b_val], returned_modules)
        import_func.assert_not_called()

    def test_list_all_covered_modules_load(self):
        module_a_val = MagicMock()
        module_b_val = MagicMock()
        with patch.dict('sys.modules', module_a=module_a_val):
            with patch(import_patch) as import_func:
                import_func.return_value = module_b_val
                returned_modules = _list_all_covered_modules(MagicMock(), ['module_a', 'module_b'], [])

        self.assertEquals([module_a_val, module_b_val], returned_modules)
        import_func.assert_called_once_with('module_b')

    def test_list_all_covered_modules_duplicate(self):
        module_a_val = MagicMock()
        module_b_val = MagicMock()
        with patch.dict('sys.modules', module_a=module_a_val, module_b=module_b_val):
            with patch(import_patch) as import_func:
                returned_modules = _list_all_covered_modules(MagicMock(), ['module_a', 'module_b', 'module_a'], [])

        self.assertEquals([module_a_val, module_b_val], returned_modules)
        import_func.assert_not_called()

    def test_list_all_covered_modules_exclusions(self):
        module_a_val = MagicMock()
        module_b_val = MagicMock()
        logger = MagicMock()
        with patch.dict('sys.modules', module_a=module_a_val, module_b=module_b_val):
            with patch(import_patch) as import_func:
                returned_modules = _list_all_covered_modules(logger, ['module_a', 'module_b', 'module_c'],
                                                             ['module_c'])

        self.assertEquals([module_a_val, module_b_val], returned_modules)
        import_func.assert_not_called()
        logger.debug.assert_called_with("Module '%s' was excluded", 'module_c')

    @patch('coverage.results.Analysis')
    @patch('coverage.coverage')
    def test_build_module_report_zero_content(self, coverage, analysis):
        coverage._analyze.return_value = analysis
        n = analysis.numbers
        n.n_statements = 0
        n.n_excluded = 0
        n.n_missing = 0
        n.n_branches = 0
        n.n_partial_branches = 0
        n.n_missing_branches = 0

        report = _build_module_report(coverage, MagicMock())
        self.assertEquals(report.code_coverage, 100)
        self.assertEquals(report.branch_coverage, 100)
        self.assertEquals(report.branch_partial_coverage, 100)

    @patch('coverage.results.Analysis')
    @patch('coverage.coverage')
    def test_build_module_report_zero_coverage(self, coverage, analysis):
        coverage._analyze.return_value = analysis
        n = analysis.numbers
        n.n_statements = 10
        n.n_excluded = 0
        n.n_missing = 10
        n.n_branches = 10
        n.n_partial_branches = 10
        n.n_missing_branches = 10

        report = _build_module_report(coverage, MagicMock())
        self.assertEquals(report.code_coverage, 0)
        self.assertEquals(report.branch_coverage, 0)
        self.assertEquals(report.branch_partial_coverage, 0)

    @patch('coverage.results.Analysis')
    @patch('coverage.coverage')
    def test_build_module_report_half_coverage(self, coverage, analysis):
        coverage._analyze.return_value = analysis
        n = analysis.numbers
        n.n_statements = 10
        n.n_excluded = 0
        n.n_missing = 5
        n.n_branches = 10
        n.n_partial_branches = 5
        n.n_missing_branches = 5

        report = _build_module_report(coverage, MagicMock())
        self.assertEquals(report.code_coverage, 50)
        self.assertEquals(report.branch_coverage, 50)
        self.assertEquals(report.branch_partial_coverage, 50)

    @patch('coverage.coverage')
    def test_build_coverage_report_no_modules(self, coverage):
        execution_name = "mock coverage"
        execution_prefix = "mock_coverage"
        project = Mock()
        modules = []
        project.get_property.side_effect = [70, 70, 70, [], False, False, False]
        self.assertTrue(_build_coverage_report(project, MagicMock(Logger), execution_name, execution_prefix, coverage,
                                               modules) is None)

    @patch('pybuilder.plugins.python.coverage_plugin.render_report')
    @patch('coverage.coverage')
    def test_build_coverage_report_two_module(self, coverage, render_report):
        execution_name = "mock coverage"
        execution_prefix = "mock_coverage"
        project = Mock()
        modules = [Mock(__name__='module_a'), Mock(__name__='module_b')]

        project.get_property.side_effect = [70, 70, 70, False, False, False]

        module_a_coverage = Mock()
        module_a_coverage.statements = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
        module_a_coverage.excluded = []
        module_a_coverage.missing = [1, 2, 3, 4, 5]
        n = module_a_coverage.numbers
        n.n_statements = 10
        n.n_excluded = 0
        n.n_missing = 5
        n.n_branches = 8
        n.n_partial_branches = 5
        n.n_missing_branches = 5

        module_b_coverage = Mock()
        module_b_coverage.statements = [1, 2, 3, 4, 5]
        module_b_coverage.excluded = []
        module_b_coverage.missing = [1, 2]
        n = module_b_coverage.numbers
        n.n_statements = 4
        n.n_excluded = 0
        n.n_missing = 2
        n.n_branches = 8
        n.n_partial_branches = 3
        n.n_missing_branches = 3

        coverage._analyze.side_effect = [module_a_coverage, module_b_coverage]
        self.assertTrue(
            _build_coverage_report(project, MagicMock(Logger), execution_name, execution_prefix, coverage,
                                   modules) is None)
        report = render_report.call_args[0][0]
        self.assertEquals(report['overall_coverage'], 50)
        self.assertEquals(report['overall_branch_coverage'], 50)
        self.assertEquals(report['overall_branch_partial_coverage'], 50)
Exemple #48
0
class Reactor(object):
    _current_instance = None

    @staticmethod
    def current_instance():
        return Reactor._current_instance

    def __init__(self, logger, execution_manager, plugin_loader=None):
        self.logger = logger
        self.execution_manager = execution_manager
        if not plugin_loader:
            builtin_plugin_loader = BuiltinPluginLoader(self.logger)
            thirdparty_plugin_loader = ThirdPartyPluginLoader(self.logger)
            self.plugin_loader = DispatchingPluginLoader(
                self.logger, builtin_plugin_loader, thirdparty_plugin_loader)
        else:
            self.plugin_loader = plugin_loader
        self._plugins = []
        self.project = None

    def require_plugin(self, plugin):
        if plugin not in self._plugins:
            try:
                self._plugins.append(plugin)
                self.import_plugin(plugin)
            except:
                self._plugins.remove(plugin)
                raise

    def get_plugins(self):
        return self._plugins

    def get_tasks(self):
        return self.execution_manager.tasks

    def validate_project(self):
        validation_messages = self.project.validate()
        if len(validation_messages) > 0:
            raise ProjectValidationFailedException(validation_messages)

    def prepare_build(self,
                      property_overrides={},
                      project_directory=".",
                      project_descriptor="build.py"):
        Reactor._current_instance = self

        project_directory, project_descriptor = self.verify_project_directory(
            project_directory, project_descriptor)

        self.logger.debug("Loading project module from %s", project_descriptor)

        self.project = Project(basedir=project_directory)

        self.project_module = self.load_project_module(project_descriptor)

        self.apply_project_attributes()
        self.override_properties(property_overrides)

        self.logger.debug("Have loaded plugins %s", ", ".join(self._plugins))

        self.collect_tasks_and_actions_and_initializers(self.project_module)

        self.execution_manager.resolve_dependencies()

    def build(self, tasks=[], environments=[]):
        Reactor._current_instance = self

        if environments:
            self.logger.info(
                "Activated environments: %s", ", ".join(environments))

        self.execution_manager.execute_initializers(
            environments, logger=self.logger, project=self.project)

        self.log_project_properties()

        self.validate_project()

        tasks = as_list(tasks)

        if not len(tasks):
            if self.project.default_task:
                tasks += as_list(self.project.default_task)
            else:
                raise PyBuilderException("No default task given.")

        execution_plan = self.execution_manager.build_execution_plan(tasks)
        self.logger.debug("Execution plan is %s", ", ".join(
            [task.name for task in execution_plan]))

        self.logger.info(
            "Building %s version %s", self.project.name, self.project.version)
        self.logger.info("Executing build in %s", self.project.basedir)

        if len(tasks) == 1:
            self.logger.info("Going to execute task %s", tasks[0])
        else:
            list_of_tasks = ", ".join(tasks)
            self.logger.info("Going to execute tasks: %s", list_of_tasks)

        task_execution_summaries = self.execution_manager.execute_execution_plan(
            execution_plan,
            logger=self.logger,
            project=self.project,
            reactor=self)

        return BuildSummary(self.project, task_execution_summaries)

    def execute_task(self, task_name):
        execution_plan = self.execution_manager.build_execution_plan(task_name)

        self.execution_manager.execute_execution_plan(execution_plan,
                                                      logger=self.logger,
                                                      project=self.project,
                                                      reactor=self)

    def override_properties(self, property_overrides):
        for property_override in property_overrides:
            self.project.set_property(
                property_override, property_overrides[property_override])

    def log_project_properties(self):
        formatted = ""
        for key in sorted(self.project.properties):
            formatted += "\n%40s : %s" % (key, self.project.get_property(key))
        self.logger.debug("Project properties: %s", formatted)

    def import_plugin(self, plugin):
        self.logger.debug("Loading plugin '%s'", plugin)
        plugin_module = self.plugin_loader.load_plugin(self.project, plugin)
        self.collect_tasks_and_actions_and_initializers(plugin_module)

    def collect_tasks_and_actions_and_initializers(self, project_module):
        for name in dir(project_module):
            candidate = getattr(project_module, name)

            if hasattr(candidate, NAME_ATTRIBUTE):
                name = getattr(candidate, NAME_ATTRIBUTE)
            elif hasattr(candidate, "__name__"):
                name = candidate.__name__
            description = getattr(candidate, DESCRIPTION_ATTRIBUTE) if hasattr(
                candidate, DESCRIPTION_ATTRIBUTE) else ""

            if hasattr(candidate, TASK_ATTRIBUTE) and getattr(candidate, TASK_ATTRIBUTE):
                dependencies = getattr(candidate, DEPENDS_ATTRIBUTE) if hasattr(
                    candidate, DEPENDS_ATTRIBUTE) else None

                self.logger.debug("Found task %s", name)
                self.execution_manager.register_task(
                    Task(name, candidate, dependencies, description))

            elif hasattr(candidate, ACTION_ATTRIBUTE) and getattr(candidate, ACTION_ATTRIBUTE):
                before = getattr(candidate, BEFORE_ATTRIBUTE) if hasattr(
                    candidate, BEFORE_ATTRIBUTE) else None
                after = getattr(candidate, AFTER_ATTRIBUTE) if hasattr(
                    candidate, AFTER_ATTRIBUTE) else None

                only_once = False
                if hasattr(candidate, ONLY_ONCE_ATTRIBUTE):
                    only_once = getattr(candidate, ONLY_ONCE_ATTRIBUTE)

                self.logger.debug("Found action %s", name)
                self.execution_manager.register_action(
                    Action(name, candidate, before, after, description, only_once))

            elif hasattr(candidate, INITIALIZER_ATTRIBUTE) and getattr(candidate, INITIALIZER_ATTRIBUTE):
                environments = []
                if hasattr(candidate, ENVIRONMENTS_ATTRIBUTE):
                    environments = getattr(candidate, ENVIRONMENTS_ATTRIBUTE)

                self.execution_manager.register_initializer(
                    Initializer(name, candidate, environments, description))

    def apply_project_attributes(self):
        self.propagate_property("name")
        self.propagate_property("version")
        self.propagate_property("default_task")
        self.propagate_property("summary")
        self.propagate_property("home_page")
        self.propagate_property("description")
        self.propagate_property("authors")
        self.propagate_property("license")
        self.propagate_property("url")

    def propagate_property(self, property):
        if hasattr(self.project_module, property):
            value = getattr(self.project_module, property)
            setattr(self.project, property, value)

    def load_project_module(self, project_descriptor):
        try:
            return imp.load_source("build", project_descriptor)
        except ImportError as e:
            raise PyBuilderException(
                "Error importing project descriptor %s: %s" % (project_descriptor, e))

    def verify_project_directory(self, project_directory, project_descriptor):
        project_directory = os.path.abspath(project_directory)

        if not os.path.exists(project_directory):
            raise PyBuilderException(
                "Project directory does not exist: %s", project_directory)

        if not os.path.isdir(project_directory):
            raise PyBuilderException(
                "Project directory is not a directory: %s", project_directory)

        project_descriptor_full_path = os.path.join(
            project_directory, project_descriptor)

        if not os.path.exists(project_descriptor_full_path):
            raise PyBuilderException(
                "Project directory does not contain descriptor file: %s",
                project_descriptor_full_path)

        if not os.path.isfile(project_descriptor_full_path):
            raise PyBuilderException(
                "Project descriptor is not a file: %s", project_descriptor_full_path)

        return project_directory, project_descriptor_full_path