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"), "")
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)
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" ])
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)
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)
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
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
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)
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, )
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")
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)
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"))
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"))
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}" )
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' ])
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"))
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")
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"))
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)
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