def test_length_is_one_after_adding_same_requirement_twice( current_platform, requirement_parser ): requirement_set = RequirementSet(current_platform) requirement_set.add(requirement_parser.parse("pypi2nix")) requirement_set.add(requirement_parser.parse("pypi2nix")) assert len(requirement_set) == 1
def test_versions_add_if_same_requirement_is_added_twice(current_platform): requirement_set = RequirementSet(current_platform) requirement_set.add(requirement_parser.parse("pypi2nix <= 2.0")) requirement_set.add(requirement_parser.parse("pypi2nix >= 1.9")) requirement = requirement_set.requirements["pypi2nix"] assert isinstance(requirement, VersionRequirement) assert len(requirement.version()) == 2
def test_pip_downloads_sources_to_target_directory(pip, project_dir, current_platform): download_path = os.path.join(project_dir, "download") requirements = RequirementSet(current_platform) requirements.add(requirement_parser.parse("six")) pip.download_sources(requirements=requirements, target_directory=download_path) assert list_files(download_path)
def test_install_six_yields_non_empty_freeze_output(pip, project_dir, download_dir, current_platform): requirements = RequirementSet(current_platform) requirements.add(requirement_parser.parse("six")) pip.download_sources(requirements, download_dir) pip.install(requirements, source_directories=[download_dir]) assert pip.freeze()
def wrapper(requirement_lines: List[str]) -> List[Wheel]: requirements = RequirementSet(current_platform) for line in requirement_lines: requirements.add(requirement_parser.parse(line)) wheel_paths = wheel_builder.build(requirements) metadata_fetcher = MetadataFetcher(generated_sources, logger, requirement_parser, pypi) return metadata_fetcher.main(wheel_paths, current_platform, wheel_builder.source_distributions)
def test_pip_with_data_directory_index_can_download_six( pip_from_data_directory: VirtualenvPip, download_dir: str, requirement_parser: RequirementParser, current_platform: TargetPlatform, ) -> None: requirements = RequirementSet(current_platform) requirements.add(requirement_parser.parse("six")) pip_from_data_directory.download_sources(requirements, download_dir)
def wrapper(requirement_lines: List[str]) -> List[Wheel]: requirements = RequirementSet(current_platform) for line in requirement_lines: requirements.add(requirement_parser.parse(line)) wheel_paths = wheel_builder.build(requirements) stage2 = Stage2(sources_for_test_packages, logger, requirement_parser, pypi) return stage2.main( wheel_paths, current_platform, wheel_builder.additional_build_dependencies )
def test_pip_without_index_cannot_download_six( pip_without_index: VirtualenvPip, download_dir: str, requirement_parser: RequirementParser, current_platform: TargetPlatform, ) -> None: requirements = RequirementSet(current_platform) requirements.add(requirement_parser.parse("six")) with pytest.raises(PipFailed): pip_without_index.download_sources(requirements, download_dir)
def build_dependencies(self, target_platform: TargetPlatform) -> RequirementSet: build_dependencies = RequirementSet(target_platform) if self.pyproject_toml is not None: build_dependencies += self.pyproject_toml.build_dependencies( target_platform ) if self.setup_cfg is not None: build_dependencies += self.setup_cfg.build_dependencies(target_platform) return build_dependencies.filter( lambda requirement: requirement.name != self.name )
def test_can_add_build_dependencies_to_wheel( wheel: Wheel, current_platform: TargetPlatform, requirement_parser: RequirementParser, ): build_dependencies = RequirementSet(current_platform) build_dependencies.add(requirement_parser.parse("dep1")) build_dependencies.add(requirement_parser.parse("dep2")) wheel.add_build_dependencies(build_dependencies) assert "dep1" in wheel.build_dependencies(current_platform) assert "dep2" in wheel.build_dependencies(current_platform)
def test_install_six_yields_non_empty_freeze_output( pip: Pip, project_dir, download_dir, current_platform, requirement_parser ): lib_dir = os.path.join(project_dir, "lib") requirements = RequirementSet(current_platform) requirements.add(requirement_parser.parse("six")) pip.download_sources(requirements, download_dir) pip.install( requirements, source_directories=[download_dir], target_directory=lib_dir ) assert pip.freeze([lib_dir])
def test_pip_downloads_sources_to_target_directory( pip: Pip, project_dir: str, current_platform: TargetPlatform, requirement_parser: RequirementParser, ): download_path = Path(project_dir) / "download" requirements = RequirementSet(current_platform) requirements.add(requirement_parser.parse("six")) pip.download_sources(requirements=requirements, target_directory=download_path) assert download_path.list_files()
def test_freeze_respects_additional_python_path(pip, project_dir, current_platform): prefix = os.path.join(project_dir, "custom-prefix") download_dir = os.path.join(project_dir, "download") requirements = RequirementSet(current_platform) requirements.add(requirement_parser.parse("six")) pip.download_sources(requirements, download_dir) pip.install( requirements, target_directory=prefix, source_directories=[download_dir] ) freeze_without_six = pip.freeze() freeze_with_six = pip.freeze(python_path=[prefix]) assert len(freeze_without_six) < len(freeze_with_six)
def source_distribution_archive(pip, requirement, download_dir, current_platform): requirement_set = RequirementSet(current_platform) requirement_set.add(requirement) pip.download_sources(requirement_set, download_dir) for file_name in os.listdir(download_dir): if file_name.startswith(requirement.name()): return Archive(path=os.path.join(download_dir, file_name)) else: raise Exception( "Could not download source distribution for `{}`".format( requirement.name()))
def wheel(current_platform): build_dependencies = RequirementSet(current_platform) dependencies = RequirementSet(current_platform) return Wheel( name="test-wheel", version="1.0", deps=dependencies, homepage="https://example.test", license="", description="description", build_dependencies=build_dependencies, target_platform=current_platform, )
def __init__( self, platform: TargetPlatform, requirement_parser: RequirementParser, logger: Logger, project_directory: str, ): self.platform = platform self.requirement_set = RequirementSet(platform) self.requirement_parser = requirement_parser self.logger = logger self._project_directory = project_directory self._sources = Sources()
def test_can_understand_wheel_dependecies( current_platform: TargetPlatform, requirement_parser: RequirementParser): runtime_dependencies = RequirementSet(current_platform) runtime_dependency = requirement_parser.parse("runtime_dependency") runtime_dependencies.add(runtime_dependency) build_dependencies = RequirementSet(current_platform) build_dependency = requirement_parser.parse("build_dependency") build_dependencies.add(build_dependency) wheel = Wheel( name="testpackage", version="", deps=runtime_dependencies, target_platform=current_platform, license="", homepage="", description="", build_dependencies=build_dependencies, ) requirement = requirement_parser.parse("testpackage") dependency_graph = DependencyGraph() dependency_graph.import_wheel(wheel, requirement_parser) assert dependency_graph.is_buildtime_dependency(requirement, build_dependency) assert dependency_graph.is_runtime_dependency(requirement, runtime_dependency)
def test_pip_can_install_wheels_previously_downloaded(pip, project_dir, current_platform): download_directory = os.path.join(project_dir, "download") target_directory = os.path.join(project_dir, "wheels") requirements = RequirementSet(current_platform) requirements.add(requirement_parser.parse("six")) pip.download_sources(requirements, download_directory) pip.build_wheels( requirements=requirements, source_directories=[download_directory], target_directory=target_directory, ) assert list_files(target_directory) assert any(map(lambda x: x.endswith(".whl"), list_files(target_directory)))
def test_elements_from_both_sets_can_be_found_in_sum_of_sets(current_platform): left = RequirementSet(current_platform) left.add(requirement_parser.parse("test1")) right = RequirementSet(current_platform) right.add(requirement_parser.parse("test2")) sum = left + right assert "test1" in sum assert "test2" in sum
def test_that_extras_are_preserved_when_converting_to_and_from_a_file( requirement_parser: RequirementParser, requirement_set: RequirementSet, current_platform: TargetPlatform, project_dir: str, logger: Logger, ): requirement_set.add(requirement_parser.parse("req[extra1]")) requirements_file = requirement_set.to_file(project_dir, current_platform, requirement_parser, logger) new_requirements_set = RequirementSet.from_file(requirements_file, current_platform, requirement_parser, logger) requirement = new_requirements_set["req"] assert requirement.extras() == {"extra1"}
def __init__( self, platform: TargetPlatform, requirement_parser: RequirementParser, logger: Logger, project_directory: str, base_dependency_graph: DependencyGraph, ): self.platform = platform self.requirement_set = RequirementSet(platform) self.requirement_parser = requirement_parser self.logger = logger self._project_directory = project_directory self._sources = Sources() self._base_dependency_graph = base_dependency_graph
class RequirementsCollector: def __init__( self, platform: TargetPlatform, requirement_parser: RequirementParser, logger: Logger, project_directory: str, ): self.platform = platform self.requirement_set = RequirementSet(platform) self.requirement_parser = requirement_parser self.logger = logger self._project_directory = project_directory self._sources = Sources() def requirements(self) -> RequirementSet: return self.requirement_set def add_line(self, line: str) -> None: requirement = self.requirement_parser.parse(line) if isinstance(requirement, PathRequirement): requirement = requirement.change_path( lambda path: self._handle_requirements_path( name=requirement.name(), path=path)) self.requirement_set.add(requirement) def add_file(self, file_path: str) -> None: requirements_file = RequirementsFile(file_path, self._project_directory, self.requirement_parser, self.logger) requirements_file.process() self._sources.update(requirements_file.sources()) added_requirements = RequirementSet.from_file(requirements_file, self.platform, self.requirement_parser, self.logger) self.requirement_set += added_requirements def sources(self) -> Sources: sources = Sources() sources.update(self.requirement_set.sources()) sources.update(self._sources) return sources def _handle_requirements_path(self, name: str, path: str) -> str: self._sources.add(name, PathSource(path)) return os.path.abspath(path)
def install( self, requirements: RequirementSet, source_directories: List[str], target_directory: Optional[str] = None, ) -> None: if not requirements: return if target_directory is None: target_directory = self.default_lib_directory requirements_files = [ requirements.to_file( self.project_directory, self.target_platform).processed_requirements_file_path() ] self.build_from_nix_file( command="exit", file_path=INSTALL_NIX, nix_arguments=self.nix_arguments( requirements_files=requirements_files, wheel_cache_dir=self.wheel_cache_dir, target_directory=target_directory, sources_directories=source_directories, ), )
def test_install_does_not_install_anything_with_empty_requirements( pip: Pip, project_dir, current_platform ): target_directory = os.path.join(project_dir, "target_dir") os.makedirs(target_directory) pip.install(RequirementSet(current_platform), [], target_directory) assert not os.listdir(target_directory)
def test_pip_downloads_nothing_when_no_requirements_are_given( pip: Pip, download_dir, current_platform ): pip.download_sources( requirements=RequirementSet(current_platform), target_directory=download_dir ) assert not list_files(download_dir)
def build( self, requirements: RequirementSet, setup_requirements: Optional[RequirementSet] = None, ) -> List[str]: self.ensure_download_directory_exists() self._ensure_wheels_directory_exists() if not setup_requirements: setup_requirements = RequirementSet(self.target_platform) else: self.logger.info("Downloading setup requirements") setup_requirements = ( self.detect_additional_build_dependencies(setup_requirements) + setup_requirements) self.logger.info("Installing setup requirements") self.pip.install( setup_requirements, target_directory=self.lib_directory, source_directories=[self.download_directory], ) self.logger.info("Downloading runtime requirements") requirements = requirements + setup_requirements detected_requirements = self.detect_additional_build_dependencies( requirements) updated_requirements = detected_requirements + requirements self.logger.info("Build wheels of setup and runtime requirements") self.pip.build_wheels(updated_requirements, self.wheel_directory, [self.download_directory]) return self.extract_wheels()
def build_wheels( self, requirements: RequirementSet, target_directory: str, source_directories: List[str], ) -> None: if not requirements: return requirements_files = [ requirements.to_file( self.project_directory, self.target_platform).processed_requirements_file_path() ] self.build_from_nix_file( command="exit", file_path=WHEEL_NIX, nix_arguments=self.nix_arguments( wheels_cache=self.wheels_cache, requirements_files=requirements_files, wheel_cache_dir=self.wheel_cache_dir, editable_sources_directory=self.editable_sources_directory(), build_directory=self.build_directory(), wheels_dir=target_directory, sources=source_directories, ), )
def test_requirement_set_respects_constraints_when_reading_from_requirement_file( tmpdir, project_dir, current_platform, requirement_parser, logger: Logger): requirements_txt = tmpdir.join("requirements.txt") constraints_txt = tmpdir.join("constraints.txt") with open(requirements_txt, "w") as f: print("test-requirement", file=f) print("-c " + str(constraints_txt), file=f) with open(constraints_txt, "w") as f: print("test-requirement <= 1.0", file=f) original_requirements_file = RequirementsFile(str(requirements_txt), project_dir, requirement_parser, logger) original_requirements_file.process() requirement_set = RequirementSet.from_file(original_requirements_file, current_platform, requirement_parser, logger) new_requirements_file = requirement_set.to_file(project_dir, current_platform, requirement_parser, logger) assert "test-requirement <= 1.0" in new_requirements_file.read()
def test_to_file_outputs_a_requirements_file_object(project_dir, current_platform): assert isinstance( RequirementSet(current_platform).to_file(project_dir, current_platform), RequirementsFile, )
def test_constraints_without_requirement_will_not_show_up_in_generated_requirement_file( tmpdir, project_dir, current_platform, requirement_parser, logger: Logger): requirements_txt = tmpdir.join("requirements.txt") constraints_txt = tmpdir.join("constraints.txt") with open(requirements_txt, "w") as f: print("test-requirement", file=f) print("-c " + str(constraints_txt), file=f) with open(constraints_txt, "w") as f: print("test-constraint == 1.0", file=f) original_requirements_file = RequirementsFile(str(requirements_txt), project_dir, requirement_parser, logger) original_requirements_file.process() requirement_set = RequirementSet.from_file(original_requirements_file, current_platform, requirement_parser, logger) new_requirements_file = requirement_set.to_file(project_dir, current_platform, requirement_parser, logger) assert "test-constraint" not in new_requirements_file.read()