Example #1
0
    def test_not_include_thoth_prereleases_allowed(self, builder_context: PipelineBuilderContext) -> None:
        """Test not including this pipeline unit."""
        builder_context.recommendation_type = RecommendationType.LATEST
        builder_context.project = Project.from_strings(self._CASE_SELECTIVE_PRERELEASES_ALLOWED_PIPFILE)

        assert builder_context.is_adviser_pipeline()
        assert list(CutPreReleasesSieve.should_include(builder_context)) == []
def load_files(base_path: str) -> typing.Tuple[str, typing.Optional[str]]:
    """Load Pipfile/Pipfile.lock from path."""
    _LOGGER.info("Looking for Pipenv files located in %r directory", base_path)
    pipfile_path = Path(base_path).joinpath("Pipfile")
    pipfile_lock_path = Path(base_path).joinpath("Pipfile.lock")

    project = Project.from_files(
        pipfile_path=pipfile_path,
        pipfile_lock_path=pipfile_lock_path,
        without_pipfile_lock=not pipfile_lock_path.exists(),
    )

    if pipfile_lock_path.exists() and project.pipfile_lock.meta.hash[
            "sha256"] != project.pipfile.hash()["sha256"]:
        _LOGGER.error(
            "Pipfile hash stated in Pipfile.lock %r does not correspond to Pipfile hash %r - was Pipfile "
            "adjusted? This error is not critical.",
            project.pipfile_lock.meta.hash["sha256"][:6],
            project.pipfile.hash()["sha256"][:6],
        )

    return (
        project.pipfile.to_string(),
        project.pipfile_lock.to_string() if project.pipfile_lock else None,
    )
Example #3
0
    def test_os_sieve(self):
        """Test removal of packages based on AICoE package source index configuration.

        We keep only TensorFlow release which is from PyPI and manylinux2010 build as there is no match on OS release.
        """
        package_versions = self._get_packages_aicoe()
        sieve_context = SieveContext.from_package_versions(package_versions)

        # Do not assign runtime environment intentionally - it will default to no environment.
        project = Project.from_strings(
            pipfile_str=self._PIPFILE_CONTENT_AICOE,
            runtime_environment=RuntimeEnvironment.from_dict(
                {"operating_system": {
                    "name": "rhel",
                    "version": "7.5"
                }}))
        os_sieve = OperatingSystemSieve(graph=None, project=project)
        os_sieve.run(sieve_context)

        expected = {
            ("pytest", "3.0.0", "https://pypi.org/simple"),
            ("tensorflow", "1.9.0", "https://pypi.org/simple"),
            # Filtering out this entry is left on another sieve which ensures runtime environment compatibility.
            ("tensorflow", "1.9.0",
             "https://tensorflow.pypi.thoth-station.ninja/index/manylinux2010/jemalloc/simple/"
             ),
            # These are filtered out:
            # ("tensorflow", "1.9.0", "https://tensorflow.pypi.thoth-station.ninja/index/os/fedora/30/jemalloc/simple/"),
            # ("tensorflow", "1.9.0", "https://tensorflow.pypi.thoth-station.ninja/index/os/rhel/7.6/jemalloc/simple/")
        }

        assert set(sieve_context.iter_direct_dependencies_tuple()) == expected
Example #4
0
    def test_python_version_mismatch(self) -> None:
        """Test when python version stated in Pipfile does not match with the one provided in the configuration."""
        context = flexmock(project=Project.from_strings(
            self._CASE_PIPFILE_PYTHON),
                           stack_info=[])
        context.project.runtime_environment.operating_system.name = "rhel"
        context.project.runtime_environment.operating_system.version = "8"
        context.project.runtime_environment.python_version = "3.8"

        boot = PythonVersionBoot()
        with PythonVersionBoot.assigned_context(context):
            boot.run()

        assert context.project.runtime_environment.operating_system.name == "rhel"
        assert context.project.runtime_environment.operating_system.version == "8"
        assert context.project.runtime_environment.python_version == "3.8"
        assert context.stack_info == [{
            "message":
            "Python version stated in Pipfile ('3.6') does not match with the one "
            "specified in the Thoth configuration ('3.8'), using Python version from Thoth "
            "configuration implicitly",
            "type":
            "WARNING",
            "link":
            jl("py_version"),
        }]
Example #5
0
    def test_no_clash(self) -> None:
        """Test raising no exception raised if clash occurs."""
        context = flexmock(project=Project.from_strings(self._CASE_PIPFILE_NOT_CLASHED))
        boot = VersionClashBoot()

        with VersionClashBoot.assigned_context(context):
            boot.run()
Example #6
0
def post_provenance_python(application_stack: dict,
                           origin: str = None,
                           debug: bool = False,
                           force: bool = False):
    """Check provenance for the given application stack."""
    parameters = locals()

    try:
        project = Project.from_strings(application_stack["requirements"],
                                       application_stack["requirements_lock"])
    except ThothPythonException as exc:
        return {
            "parameters": parameters,
            "error": f"Invalid application stack supplied: {str(exc)}"
        }, 400
    except Exception as exc:
        return {
            "parameters": parameters,
            "error": "Invalid application stack supplied"
        }, 400

    graph = GraphDatabase()
    graph.connect()
    parameters["whitelisted_sources"] = list(
        graph.get_python_package_index_urls())

    force = parameters.pop("force", False)
    cached_document_id = _compute_digest_params(
        dict(**project.to_dict(),
             origin=origin,
             whitelisted_sources=parameters["whitelisted_sources"]))

    timestamp_now = int(time.mktime(datetime.datetime.utcnow().timetuple()))
    cache = ProvenanceCacheStore()
    cache.connect()

    if not force:
        try:
            cache_record = cache.retrieve_document_record(cached_document_id)
            if cache_record[
                    "timestamp"] + Configuration.THOTH_CACHE_EXPIRATION > timestamp_now:
                return {
                    "analysis_id": cache_record.pop("analysis_id"),
                    "cached": True,
                    "parameters": parameters
                }, 202
        except CacheMiss:
            pass

    response, status = _do_schedule(
        parameters,
        _OPENSHIFT.schedule_provenance_checker,
        output=Configuration.THOTH_PROVENANCE_CHECKER_OUTPUT)
    if status == 202:
        cache.store_document_record(cached_document_id, {
            "analysis_id": response["analysis_id"],
            "timestamp": timestamp_now
        })

    return response, status
Example #7
0
    def test_no_python_pipfile(self) -> None:
        """Test assigning Python version from Pipfile."""
        context = flexmock(project=Project.from_strings(
            self._CASE_PIPFILE_NO_PYTHON),
                           stack_info=[])
        context.project.runtime_environment.operating_system.name = "rhel"
        context.project.runtime_environment.operating_system.version = "8"
        context.project.runtime_environment.python_version = "3.6"

        boot = PythonVersionBoot()
        with PythonVersionBoot.assigned_context(context):
            boot.run()

        assert context.project.runtime_environment.operating_system.name == "rhel"
        assert context.project.runtime_environment.operating_system.version == "8"
        assert context.project.runtime_environment.python_version == "3.6"
        assert context.stack_info == [{
            "message":
            "No version of Python specified explicitly, assigning the one "
            "found in Thoth's configuration: '3.6'",
            "type":
            "WARNING",
            "link":
            jl("py_version"),
        }]
Example #8
0
    def test_os_sieve_no_error(self):
        """Test no error raised if no packages satisfy OS specific requirements."""
        package_versions = [
            PackageVersion(
                name="tensorflow",
                version="==1.9.0",
                index=Source(
                    "https://tensorflow.pypi.thoth-station.ninja/index/fedora/30/jemalloc/simple/"
                ),
                develop=False,
            )
        ]

        sieve_context = SieveContext.from_package_versions(package_versions)
        project = Project.from_strings(
            pipfile_str=self._PIPFILE_CONTENT_AICOE,
            runtime_environment=RuntimeEnvironment.from_dict(
                {"operating_system": {
                    "name": "ubi",
                    "version": "9"
                }}))
        os_sieve = OperatingSystemSieve(graph=None, project=project)
        os_sieve.run(sieve_context)

        assert set(sieve_context.iter_direct_dependencies_tuple()) == {
            ("tensorflow", "1.9.0",
             "https://tensorflow.pypi.thoth-station.ninja/index/fedora/30/jemalloc/simple/"
             ),
        }
Example #9
0
    def test_from_pip_compile_files_example_dir1(self) -> None:
        """Test loading only if requirements.txt is present."""
        with cwd(os.path.join(self.data_dir, "requirements", "example_dir1")):
            with pytest.raises(FileNotFoundError):
                Project.from_pip_compile_files()

            project = Project.from_pip_compile_files(allow_without_lock=True)

            assert project.pipfile_lock is None
            assert list(project.iter_dependencies()) == [
                PackageVersion(name="click",
                               version="*",
                               develop=False,
                               hashes=[],
                               index=Source("https://pypi.org/simple"))
            ]
Example #10
0
    def test_run_dev(self, context: Context) -> None:
        """Test discarding user's lock file if development dependencies are not present in lock but provided."""
        pipfile = str(self.data_dir / "projects" / "dev" / "Pipfile")
        pipfile_lock = str(self.data_dir / "projects" / "dev" / "Pipfile.lock")

        project = Project.from_files(pipfile_path=pipfile,
                                     pipfile_lock_path=pipfile_lock)

        assert project.pipfile.dev_packages.packages
        assert project.pipfile_lock.dev_packages.packages

        # Remove packages.
        project.pipfile_lock.dev_packages.packages.clear()
        context.cli_parameters["dev"] = True

        context.project = project

        unit = self.UNIT_TESTED()
        with unit.assigned_context(context):
            unit.run()

        assert project.pipfile.dev_packages.packages
        assert not project.pipfile_lock, "Lock file was not removed from the input"
        assert len(context.stack_info) == 1
        assert self.verify_justification_schema(context.stack_info)
Example #11
0
def _instantiate_project(
    requirements: str,
    requirements_locked: typing.Optional[str],
    files: bool,
    runtime_environment: RuntimeEnvironment = None,
):
    """Create Project instance based on arguments passed to CLI."""
    if files:
        with open(requirements, "r") as requirements_file:
            requirements = requirements_file.read()

        if requirements_locked:
            with open(requirements_locked, "r") as requirements_file:
                requirements_locked = requirements_file.read()
            del requirements_file
    else:
        # We we gather values from env vars, un-escape new lines.
        requirements = requirements.replace("\\n", "\n")
        if requirements_locked:
            requirements_locked = requirements_locked.replace("\\n", "\n")

    pipfile = Pipfile.from_string(requirements)
    pipfile_lock = (
        PipfileLock.from_string(requirements_locked, pipfile)
        if requirements_locked
        else None
    )
    project = Project(
        pipfile=pipfile,
        pipfile_lock=pipfile_lock,
        runtime_environment=runtime_environment or RuntimeEnvironment.from_dict({}),
    )

    return project
Example #12
0
    def test_add_package(self):
        """Test add package."""
        pipfile = Pipfile.from_file(os.path.join(self.data_dir, "pipfiles", "Pipfile_test1"))
        pipfile_lock = PipfileLock.from_file(os.path.join(self.data_dir, "pipfiles", "Pipfile_test1.lock"))
        project = Project(pipfile=pipfile, pipfile_lock=pipfile_lock)

        assert "selinon" not in project.pipfile.packages.packages
        project.add_package("selinon", "==1.0.0")

        assert "selinon" in project.pipfile.packages.packages
        assert project.pipfile.packages["selinon"].version == "==1.0.0"
        assert project.pipfile.packages["selinon"].index is None
        assert project.pipfile.packages["selinon"].develop is False

        # Do not add the package to the lock - lock has to be explicitly done.
        assert "selinon" not in project.pipfile_lock.packages.packages
Example #13
0
    def test_no_python_config(self) -> None:
        """Test assigning Python version from Thoth's config file."""
        context = flexmock(project=Project.from_strings(
            self._CASE_PIPFILE_PYTHON),
                           stack_info=[])
        context.project.runtime_environment.operating_system.name = "rhel"
        context.project.runtime_environment.operating_system.version = "8"

        assert context.project.runtime_environment.python_version is None

        boot = PythonVersionBoot()
        with PythonVersionBoot.assigned_context(context):
            boot.run()

        assert context.project.runtime_environment.operating_system.name == "rhel"
        assert context.project.runtime_environment.operating_system.version == "8"
        assert context.project.runtime_environment.python_version == "3.6"
        assert context.stack_info == [
            {
                'Message':
                'No version of Python specified in the configuration, using '
                "Python version found in Pipfile: '3.6'",
                'type':
                'WARNING'
            },
        ]
Example #14
0
def _instantiate_project(
    requirements: str,
    requirements_locked: Optional[str] = None,
    runtime_environment: RuntimeEnvironment = None,
):
    """Create Project instance based on arguments passed to CLI."""
    try:
        with open(requirements, "r") as requirements_file:
            requirements = requirements_file.read()
    except (OSError, FileNotFoundError):
        # We we gather values from env vars, un-escape new lines.
        requirements = requirements.replace("\\n", "\n")

    if requirements_locked:
        try:
            with open(requirements_locked, "r") as requirements_file:
                requirements_locked = requirements_file.read()
        except (OSError, FileNotFoundError):
            # We we gather values from env vars, un-escape new lines.
            requirements_locked = requirements_locked.replace("\\n", "\n")

    pipfile = Pipfile.from_string(requirements)
    pipfile_lock = PipfileLock.from_string(
        requirements_locked, pipfile) if requirements_locked else None
    project = Project(
        pipfile=pipfile,
        pipfile_lock=pipfile_lock,
        runtime_environment=runtime_environment
        or RuntimeEnvironment.from_dict({}),
    )

    return project
Example #15
0
    def test_pre_releases_disallowed_removal(self, context: Context,
                                             package_name: str,
                                             package_version: str) -> None:
        """Test no removals if pre-releases are allowed."""
        pv = PackageVersion(
            name=package_name,
            version=f"=={package_version}",
            index=Source("https://pypi.org/simple"),
            develop=False,
        )

        project = Project.from_strings(self._CASE_GLOBAL_DISALLOWED_PIPFILE)
        context.project = project
        sieve = self.UNIT_TESTED()
        sieve.update_configuration({
            "package_name":
            None,
            "allow_prereleases":
            project.pipfile.thoth.allow_prereleases
        })

        assert not context.stack_info
        with self.UNIT_TESTED.assigned_context(context):
            assert list(sieve.run(p for p in [pv])) == []

        assert len(context.stack_info) == 1
        assert self.verify_justification_schema(context.stack_info)
Example #16
0
    def test_remove_pre_releases_disallowed_noop(self, context: Context,
                                                 package_name: str,
                                                 package_version: str) -> None:
        """Test NOT removing dependencies based on pre-release configuration."""
        pv = PackageVersion(
            name=package_name,
            version=f"=={package_version}",
            index=Source("https://pypi.org/simple"),
            develop=False,
        )

        project = Project.from_strings(self._CASE_GLOBAL_DISALLOWED_PIPFILE)
        context.project = project
        sieve = self.UNIT_TESTED()
        sieve.update_configuration({
            "package_name":
            None,
            "allow_prereleases":
            project.pipfile.thoth.allow_prereleases
        })

        assert not context.stack_info
        with self.UNIT_TESTED.assigned_context(context):
            assert list(sieve.run(p for p in [pv])) == [pv]

        assert not context.stack_info, "No stack information should be provided"
Example #17
0
    def post(self):
        """Get requirements file from disk."""
        input_data = self.get_json_body()

        kernel_name: str = input_data["kernel_name"]
        home = Path.home()
        store_path: Path = home.joinpath(".local/share/thoth/kernels")

        env_path = Path(store_path).joinpath(kernel_name)

        _LOGGER.info("Path used to get dependencies is: %r",
                     env_path.as_posix())

        requirements_format = "pipenv"

        pipfile_path = env_path.joinpath("Pipfile")
        pipfile_lock_path = env_path.joinpath("Pipfile.lock")

        if requirements_format == "pipenv":
            _LOGGER.debug("Get Pipfile/Pipfile.lock in %r", env_path)
            project = Project.from_files(pipfile_path=pipfile_path,
                                         pipfile_lock_path=pipfile_lock_path)

        requirements = project.pipfile.to_dict()
        requirements_locked = project.pipfile_lock.to_dict()

        self.finish(
            json.dumps({
                "requirements": requirements,
                "requirements_lock": requirements_locked
            }))
Example #18
0
    def test_remove_all_transitive_error(self):
        """Test raising of an error if all the transitive deps of a type were removed."""
        source = Source("https://pypi.org/simple")
        direct_dependencies = {
            ("tensorflow", "2.0.0", source.url):
            PackageVersion(
                name="tensorflow",
                version="==2.0.0",
                index=source,
                develop=False,
            )
        }

        paths = {
            ("tensorflow", "2.0.0", "https://pypi.org/simple"): [
                (("tensorflow", "2.0.0", "https://pypi.org/simple"),
                 ("numpy", "1.0.0rc1", "https://thoth-station.ninja/simple")),
            ]
        }

        step_context = StepContext.from_paths(direct_dependencies, paths)

        project = Project.from_strings(self._CASE_PIPFILE)
        restrict_indexes = CutPreReleases(
            graph=None,
            project=project,
            library_usage=None,
        )

        with pytest.raises(CannotRemovePackage):
            restrict_indexes.run(step_context)
Example #19
0
def _dm_stdout_output(generated_project: Project, count: int):
    """A function called if the project should be printed to stdout as a dict."""
    json.dump(generated_project.to_dict(),
              fp=sys.stdout,
              sort_keys=True,
              indent=2)
    return None
Example #20
0
    def test_stride_remove_stack(self):
        project = Project.from_strings(_PIPFILE_STR)

        direct_dependency = PackageVersion(
            name="flask",
            version="==1.0.2",
            index=Source("https://pypi.org/simple"),
            develop=False,
        )

        step_context = StepContext.from_paths(
            {direct_dependency.to_tuple(): direct_dependency},
            {direct_dependency.to_tuple(): []},
        )

        pipeline = Pipeline(
            graph=None,  # We avoid low-level testing down to thoth-storages.
            project=project,
            sieves=[],
            steps=[],
            strides=[
                (_MockStrideRemoveStack, None)
            ],
        )

        flexmock(
            pipeline,
            _prepare_direct_dependencies=lambda with_devel: [direct_dependency],
            _resolve_transitive_dependencies=lambda _: step_context,
        )

        # We raise an exception on first walk call, no stacks should be produced.
        pipeline_products = list(pipeline.conduct(limit=None, count=None))
        assert len(pipeline_products) == 0
Example #21
0
 def test_verify_multiple_should_include(
         self, builder_context: PipelineBuilderContext) -> None:
     """Verify multiple should_include calls do not loop endlessly."""
     builder_context.recommendation_type = RecommendationType.LATEST
     builder_context.project = Project.from_strings(
         self._CASE_DISALLOWED_PIPFILE)
     self.verify_multiple_should_include(builder_context)
Example #22
0
    def test_indexes_in_meta(self):
        """Check indexes being adjusted when inserting a new package."""
        package_version = PackageVersion(
            name="tensorflow",
            version="==1.9.0",
            develop=False,
            index=Source(
                "http://tensorflow.pypi.thoth-station.ninja/index/fedora28/jemalloc/simple/tensorflow/"
            ),
        )

        project = Project.from_package_versions([package_version])

        project_dict = project.to_dict()
        pipfile_dict = project_dict["requirements"]
        pipfile_lock_dict = project_dict["requirements_locked"]

        assert pipfile_lock_dict is None

        assert len(pipfile_dict["source"]) == 1
        assert pipfile_dict["source"] == [{
            "url":
            "http://tensorflow.pypi.thoth-station.ninja/index/fedora28/jemalloc/simple/tensorflow/",
            "verify_ssl":
            True,
            "name":
            "tensorflow-pypi-thoth-station-ninja",
        }]
Example #23
0
    def test_add_source(self):
        pipfile = Pipfile.from_file(
            os.path.join(self.data_dir, 'pipfiles', 'Pipfile_test1'))
        pipfile_lock = PipfileLock.from_file(
            os.path.join(self.data_dir, 'pipfiles', 'Pipfile_test1.lock'))
        project = Project(pipfile=pipfile, pipfile_lock=pipfile_lock)

        source = project.add_source(url='https://foo.bar')

        assert source.name is not None

        assert source.name in project.pipfile.meta.sources
        assert source is project.pipfile.meta.sources[source.name]

        assert source.name in project.pipfile_lock.meta.sources
        assert source is project.pipfile_lock.meta.sources[source.name]
Example #24
0
    def test_add_package(self):
        pipfile = Pipfile.from_file(
            os.path.join(self.data_dir, 'pipfiles', 'Pipfile_test1'))
        pipfile_lock = PipfileLock.from_file(
            os.path.join(self.data_dir, 'pipfiles', 'Pipfile_test1.lock'))
        project = Project(pipfile=pipfile, pipfile_lock=pipfile_lock)

        assert 'selinon' not in project.pipfile.packages.packages
        project.add_package('selinon', '==1.0.0')

        assert 'selinon' in project.pipfile.packages.packages
        assert project.pipfile.packages['selinon'].version == '==1.0.0'
        assert project.pipfile.packages['selinon'].index is None
        assert project.pipfile.packages['selinon'].develop is False

        # Do not add the package to the lock - lock has to be explicitly done.
        assert 'selinon' not in project.pipfile_lock.packages.packages
Example #25
0
    def test_clash(self) -> None:
        """Test raising an exception if a version clash occurs."""
        context = flexmock(project=Project.from_strings(self._CASE_PIPFILE_CLASHED))
        with pytest.raises(CannotProduceStack):
            boot = VersionClashBoot()

            with VersionClashBoot.assigned_context(context):
                boot.run()
Example #26
0
    def test_add_source(self):
        """Test add source."""
        pipfile = Pipfile.from_file(
            os.path.join(self.data_dir, "pipfiles", "Pipfile_test1"))
        pipfile_lock = PipfileLock.from_file(
            os.path.join(self.data_dir, "pipfiles", "Pipfile_test1.lock"))
        project = Project(pipfile=pipfile, pipfile_lock=pipfile_lock)

        source = project.add_source(url="https://foo.bar")

        assert source.name is not None

        assert source.name in project.pipfile.meta.sources
        assert source is project.pipfile.meta.sources[source.name]

        assert source.name in project.pipfile_lock.meta.sources
        assert source is project.pipfile_lock.meta.sources[source.name]
Example #27
0
    def test_add_package_develop(self):
        """Test add package develop."""
        pipfile = Pipfile.from_file(
            os.path.join(self.data_dir, "pipfiles", "Pipfile_test1"))
        pipfile_lock = PipfileLock.from_file(
            os.path.join(self.data_dir, "pipfiles", "Pipfile_test1.lock"))
        project = Project(pipfile=pipfile, pipfile_lock=pipfile_lock)

        source = Source(name="foo",
                        url="https://foo.bar",
                        verify_ssl=True,
                        warehouse=False)

        assert "selinon" not in project.pipfile.dev_packages.packages

        with pytest.raises(InternalError):
            # Trying to add package with source but source is not present in the meta.
            project.add_package("selinon",
                                "==1.0.0",
                                develop=True,
                                source=source)

        source = project.add_source(url="https://foo.bar")
        project.add_package("selinon", "==1.0.0", develop=True, source=source)

        assert "selinon" in project.pipfile.dev_packages.packages
        assert project.pipfile.dev_packages["selinon"].version == "==1.0.0"
        assert project.pipfile.dev_packages["selinon"].index.name == "foo-bar"
        assert project.pipfile.dev_packages["selinon"].develop is True
        # Do not add the package to the lock - lock has to be explicitly done.
        assert "selinon" not in project.pipfile_lock.dev_packages.packages
Example #28
0
    def test_add_package_develop(self):
        pipfile = Pipfile.from_file(
            os.path.join(self.data_dir, 'pipfiles', 'Pipfile_test1'))
        pipfile_lock = PipfileLock.from_file(
            os.path.join(self.data_dir, 'pipfiles', 'Pipfile_test1.lock'))
        project = Project(pipfile=pipfile, pipfile_lock=pipfile_lock)

        source = Source(name='foo',
                        url='https://foo.bar',
                        verify_ssl=True,
                        warehouse=False)

        assert 'selinon' not in project.pipfile.dev_packages.packages

        with pytest.raises(InternalError):
            # Trying to add package with source but source is not present in the meta.
            project.add_package('selinon',
                                '==1.0.0',
                                develop=True,
                                source=source)

        source = project.add_source(url='https://foo.bar')
        project.add_package('selinon', '==1.0.0', develop=True, source=source)

        assert 'selinon' in project.pipfile.dev_packages.packages
        assert project.pipfile.dev_packages['selinon'].version == '==1.0.0'
        assert project.pipfile.dev_packages['selinon'].index == 'foo-bar'
        assert project.pipfile.dev_packages['selinon'].develop is True
        # Do not add the package to the lock - lock has to be explicitly done.
        assert 'selinon' not in project.pipfile_lock.dev_packages.packages
Example #29
0
    def from_final_state(cls, *, context: Context, state: State) -> "Product":
        """Instantiate advised stack from final state produced by adviser's pipeline."""
        assert state.is_final(), "Instantiating product from a non-final state"

        package_versions_locked = []
        for package_tuple in state.resolved_dependencies.values():
            package_version: PackageVersion = context.get_package_version(
                package_tuple, graceful=False)

            # Fill package hashes before instantiating the final product.
            if not package_version.hashes:
                # We can re-use already existing package-version - in that case it already keeps hashes from
                # a previous product instantiation.
                hashes = context.graph.get_python_package_hashes_sha256(
                    *package_tuple)
                package_version.hashes = ["sha256:" + h for h in hashes]

                if not package_version.hashes:
                    _LOGGER.warning("No hashes found for package %r",
                                    package_tuple)

                # Fill environment markers by checking dependencies that introduced this dependency.
                # We do it only if we have no hashes - if hashes are present, the environment marker was
                # already picked (can be set to None if no marker is present).
                # For direct dependencies, dependents can return an empty set (if dependency is not
                # shared with other dependencies) and marker is propagated from PackageVersion registered in
                # Context.register_package_version.
                dependents_tuples = context.dependents[
                    package_tuple[0]][package_tuple]
                for dependent_tuple in dependents_tuples:
                    environment_marker = context.graph.get_python_environment_marker(
                        *dependent_tuple[0],
                        dependency_name=package_tuple[0],
                        dependency_version=package_tuple[1],
                        os_name=dependent_tuple[1],
                        os_version=dependent_tuple[2],
                        python_version=dependent_tuple[3],
                    )
                    if package_version.markers and environment_marker:
                        # Install dependency if any of dependents need it.
                        package_version.markers = f"({package_version.markers}) or ({environment_marker})"
                    elif not package_version.markers and environment_marker:
                        package_version.markers = environment_marker

            package_versions_locked.append(package_version)

        advised_project = Project.from_package_versions(
            packages=list(context.project.iter_dependencies(with_devel=True)),
            packages_locked=package_versions_locked,
        )

        return cls(
            project=advised_project,
            score=state.score,
            justification=state.justification,
            advised_runtime_environment=state.advised_runtime_environment,
        )
Example #30
0
 def _dm_stdout_output(count: int,
                       generated_project: Project) -> None:  # noqa: D401
     """A function called if the project should be printed to stdout as a dict."""
     _LOGGER.debug("Printing stack %d", count)
     json.dump(generated_project.to_dict(),
               fp=sys.stdout,
               sort_keys=True,
               indent=2)
     return None