def test_convert_dependencies(): package = Package('foo', '1.2.3') result = SdistBuilder.convert_dependencies(package, [ get_dependency('A', '^1.0'), get_dependency('B', '~1.0'), get_dependency('C', '1.2.3'), ]) main = [ 'A (>=1.0.0.0,<2.0.0.0)', 'B (>=1.0.0.0,<1.1.0.0)', 'C (==1.2.3.0)', ] extras = {} assert result == (main, extras) package = Package('foo', '1.2.3') package.extras = {'bar': [get_dependency('A')]} result = SdistBuilder.convert_dependencies(package, [ get_dependency('A', '>=1.2', optional=True), get_dependency('B', '~1.0'), get_dependency('C', '1.2.3'), ]) main = [ 'B (>=1.0.0.0,<1.1.0.0)', 'C (==1.2.3.0)', ] extras = {'bar': ['A (>=1.2.0.0)']} assert result == (main, extras)
def load(cls, env): # type: (Env) -> InstalledRepository """ Load installed packages. For now, it uses the pip "freeze" command. """ repo = cls() freeze_output = env.run_pip("freeze") for line in freeze_output.split("\n"): if "==" in line: name, version = re.split("={2,3}", line) repo.add_package(Package(name, version, version)) elif line.startswith("-e "): line = line[3:].strip() if line.startswith("git+"): url = line.lstrip("git+") if "@" in url: url, rev = url.rsplit("@", 1) else: rev = "master" name = url.split("/")[-1].rstrip(".git") if "#egg=" in rev: rev, name = rev.split("#egg=") package = Package(name, "0.0.0") package.source_type = "git" package.source_url = url package.source_reference = rev repo.add_package(package) return repo
def test_convert_dependencies(): package = Package("foo", "1.2.3") result = SdistBuilder.convert_dependencies( package, [ get_dependency("A", "^1.0"), get_dependency("B", "~1.0"), get_dependency("C", "1.2.3"), ], ) main = ["A>=1.0,<2.0", "B>=1.0,<1.1", "C==1.2.3"] extras = {} assert result == (main, extras) package = Package("foo", "1.2.3") package.extras = {"bar": [get_dependency("A")]} result = SdistBuilder.convert_dependencies( package, [ get_dependency("A", ">=1.2", optional=True), get_dependency("B", "~1.0"), get_dependency("C", "1.2.3"), ], ) main = ["B>=1.0,<1.1", "C==1.2.3"] extras = {"bar": ["A>=1.2"]} assert result == (main, extras) c = get_dependency("C", "1.2.3") c.python_versions = "~2.7 || ^3.6" d = get_dependency("D", "3.4.5", optional=True) d.python_versions = "~2.7 || ^3.4" package.extras = {"baz": [get_dependency("D")]} result = SdistBuilder.convert_dependencies( package, [ get_dependency("A", ">=1.2", optional=True), get_dependency("B", "~1.0"), c, d, ], ) main = ["B>=1.0,<1.1"] extra_python = ( ':python_version >= "2.7" and python_version < "2.8" ' 'or python_version >= "3.6" and python_version < "4.0"' ) extra_d_dependency = ( 'baz:python_version >= "2.7" and python_version < "2.8" ' 'or python_version >= "3.4" and python_version < "4.0"' ) extras = {extra_python: ["C==1.2.3"], extra_d_dependency: ["D==3.4.5"]} assert result == (main, extras)
def test_convert_dependencies(): package = Package('foo', '1.2.3') result = SdistBuilder.convert_dependencies(package, [ get_dependency('A', '^1.0'), get_dependency('B', '~1.0'), get_dependency('C', '1.2.3'), ]) main = [ 'A>=1.0.0.0,<2.0.0.0', 'B>=1.0.0.0,<1.1.0.0', 'C==1.2.3.0', ] extras = {} assert result == (main, extras) package = Package('foo', '1.2.3') package.extras = {'bar': [get_dependency('A')]} result = SdistBuilder.convert_dependencies(package, [ get_dependency('A', '>=1.2', optional=True), get_dependency('B', '~1.0'), get_dependency('C', '1.2.3'), ]) main = [ 'B>=1.0.0.0,<1.1.0.0', 'C==1.2.3.0', ] extras = {'bar': ['A>=1.2.0.0']} assert result == (main, extras) c = get_dependency('C', '1.2.3') c.python_versions = '~2.7 || ^3.6' d = get_dependency('D', '3.4.5', optional=True) d.python_versions = '~2.7 || ^3.4' package.extras = {'baz': [get_dependency('D')]} result = SdistBuilder.convert_dependencies(package, [ get_dependency('A', '>=1.2', optional=True), get_dependency('B', '~1.0'), c, d ]) main = [ 'B>=1.0.0.0,<1.1.0.0', ] extra_python = ( ':(python_version >= "2.7.0.0" and python_version < "2.8.0.0") ' 'or (python_version >= "3.6.0.0" and python_version < "4.0.0.0")') extra_d_dependency = ( 'baz:(python_version >= "2.7.0.0" and python_version < "2.8.0.0") ' 'or (python_version >= "3.4.0.0" and python_version < "4.0.0.0")') extras = { extra_python: ['C==1.2.3.0'], extra_d_dependency: ['D==3.4.5.0'], } assert result == (main, extras)
def package(self, name: str, version: str, extras: Union[list, None] = None) -> Package: try: index = self._packages.index(Package(name, version, version)) return self._packages[index] except ValueError: if extras is None: extras = [] release_info = self.get_release_info(name, version) package = Package(name, version, version) requires_dist = release_info['requires_dist'] or [] for req in requires_dist: try: dependency = dependency_from_pep_508(req) except InvalidMarker: # Invalid marker # We strip the markers hoping for the best req = req.split(';')[0] dependency = dependency_from_pep_508(req) if dependency.extras: for extra in dependency.extras: if extra not in package.extras: package.extras[extra] = [] package.extras[extra].append(dependency) if not dependency.is_optional(): package.requires.append(dependency) # Adding description package.description = release_info.get('summary', '') # Adding hashes information package.hashes = release_info['digests'] # Activate extra dependencies for extra in extras: if extra in package.extras: for dep in package.extras[extra]: dep.activate() package.requires += package.extras[extra] self._packages.append(package) return package
def specs_from_fixtures(cls, fixture_name): if fixture_name in cls._specs_from_fixtures: return cls._specs_from_fixtures[fixture_name] packages_by_name = {} with open(os.path.join(FIXTURE_INDEX_DIR, fixture_name + '.json')) as fd: content = json.load(fd) for name, releases in content.items(): packages_by_name[name] = [] for release in releases: package = Package(name, release['version'], release['version']) for dependency_name, requirements in release[ 'dependencies'].items(): package.requires.append( Dependency(dependency_name, requirements)) packages_by_name[name].append(package) packages_by_name[name].sort( key=cmp_to_key(lambda x, y: 0 if x.version[1] == y.version[ 1] else -1 * int(less_than(x[1], y[1]) or -1))) return packages_by_name
def get_package_from_file(cls, file_path): # type: (Path) -> Package if file_path.suffix == ".whl": meta = pkginfo.Wheel(str(file_path)) else: # Assume sdist meta = pkginfo.SDist(str(file_path)) package = Package(meta.name, meta.version) package.source_type = "file" package.source_url = file_path.as_posix() package.description = meta.summary for req in meta.requires_dist: dep = dependency_from_pep_508(req) for extra in dep.in_extras: if extra not in package.extras: package.extras[extra] = [] package.extras[extra].append(dep) if not dep.is_optional(): package.requires.append(dep) if meta.requires_python: package.python_versions = meta.requires_python return package
def test_accepts_fails_with_python_versions_mismatch(): dependency = Dependency('A', '^1.0') dependency.python_versions = '^3.6' package = Package('B', '1.4') package.python_versions = '~3.5' assert not dependency.accepts(package)
def search(self, query): results = [] search = {"q": query} response = session().get(self._url + "search", params=search) content = parse(response.content, namespaceHTMLElements=False) for result in content.findall(".//*[@class='package-snippet']"): name = result.find("h3/*[@class='package-snippet__name']").text version = result.find( "h3/*[@class='package-snippet__version']").text if not name or not version: continue description = result.find( "p[@class='package-snippet__description']").text if not description: description = "" try: result = Package(name, version, description) result.description = to_str(description.strip()) results.append(result) except ParseVersionError: self._log( 'Unable to parse version "{}" for the {} package, skipping' .format(version, name), level="debug", ) return results
def test_accepts_python_versions(): dependency = Dependency('A', '^1.0') dependency.python_versions = '^3.6' package = Package('A', '1.4') package.python_versions = '~3.6' assert dependency.accepts(package)
def test_accepts_python_versions(): dependency = Dependency("A", "^1.0") dependency.python_versions = "^3.6" package = Package("A", "1.4") package.python_versions = "~3.6" assert dependency.accepts(package)
def find_packages( self, name, # type: str constraint=None, # type: Union[Constraint, str, None] extras=None # type: Union[list, None] ): # type: (...) -> List[Package] """ Find packages on the remote server. """ packages = [] if constraint is not None and not isinstance(constraint, BaseConstraint): version_parser = VersionParser() constraint = version_parser.parse_constraints(constraint) info = self.get_package_info(name) versions = [] for version, release in info['releases'].items(): if (not constraint or (constraint and constraint.matches(Constraint('=', version)))): versions.append(version) for version in versions: packages.append(Package(name, version, version)) return packages
def test_accepts_fails_with_python_versions_mismatch(): dependency = Dependency("A", "^1.0") dependency.python_versions = "^3.6" package = Package("B", "1.4") package.python_versions = "~3.5" assert not dependency.accepts(package)
def test_package_add_dependency_vcs_category_default_main(): package = Package("foo", "0.1.0") dependency = package.add_dependency( "poetry", constraint={"git": "https://github.com/python-poetry/poetry.git"}) assert dependency.category == "main"
def search(self, query, mode=0): results = [] search = {"name": query} if mode == self.SEARCH_FULLTEXT: search["summary"] = query client = ServerProxy("https://pypi.python.org/pypi") hits = client.search(search, "or") for hit in hits: try: result = Package(hit["name"], hit["version"], hit["version"]) result.description = to_str(hit["summary"]) results.append(result) except ParseVersionError: self._log( 'Unable to parse version "{}" for the {} package, skipping'.format( hit["version"], hit["name"] ), level="debug", ) return results
def get_package_from_file(cls, file_path): # type: (Path) -> Package info = Inspector().inspect(file_path) if not info["name"]: raise RuntimeError( "Unable to determine the package name of {}".format(file_path)) package = Package(info["name"], info["version"]) package.source_type = "file" package.source_url = file_path.as_posix() package.description = info["summary"] for req in info["requires_dist"]: dep = dependency_from_pep_508(req) for extra in dep.in_extras: if extra not in package.extras: package.extras[extra] = [] package.extras[extra].append(dep) if not dep.is_optional(): package.requires.append(dep) if info["requires_python"]: package.python_versions = info["requires_python"] return package
def create(cls, pac_file: Path, modified=False): local_config = TomlFile(pac_file.as_posix()).read() if "package" not in local_config: raise RuntimeError("[package] section not found in {}".format( pac_file.name)) # Checking validity cls.check(local_config) name = str(pac_file.parent).replace("/", ".") version = local_config["package"]["version"] if not modified: package = Package(name, version) else: old_version = _get_old_version(pac_file) package = ModifiedPackage(name, version, old_version) package.root_dir = pac_file.parent if "dependencies" in local_config: for name, constraint in local_config["dependencies"].items(): package.add_dependency(name, constraint) if "dev-dependencies" in local_config: for name, constraint in local_config["dev-dependencies"].items(): package.add_dependency(name, constraint, category="dev") return cls(pac_file, local_config, package)
def find_packages(self, name, constraint=None, extras=None, allow_prereleases=False): packages = [] if constraint is None: constraint = "*" if not isinstance(constraint, VersionConstraint): constraint = parse_constraint(constraint) if isinstance(constraint, VersionRange): if (constraint.max is not None and constraint.max.is_prerelease() or constraint.min is not None and constraint.min.is_prerelease()): allow_prereleases = True key = name if not constraint.is_any(): key = "{}:{}".format(key, str(constraint)) if self._cache.store("matches").has(key): versions = self._cache.store("matches").get(key) else: page = self._get("/{}/".format( canonicalize_name(name).replace(".", "-"))) if page is None: return [] versions = [] for version in page.versions: if version.is_prerelease() and not allow_prereleases: continue if constraint.allows(version): versions.append(version) self._cache.store("matches").put(key, versions, 5) for version in versions: package = Package(name, version) package.source_type = "legacy" package.source_reference = self.name package.source_url = self._url if extras is not None: package.requires_extras = extras packages.append(package) self._log( "{} packages found for {} {}".format(len(packages), name, str(constraint)), level="debug", ) return packages
def add_to_repo(repository, name, version, deps=None): package = Package(name, version) if deps: for dep_name, dep_constraint in deps.items(): package.add_dependency(dep_name, dep_constraint) repository.add_package(package)
def load(cls, env): # type: (Env) -> InstalledRepository """ Load installed packages. For now, it uses the pip "freeze" command. """ repo = cls() seen = set() for entry in env.sys_path: for distribution in sorted( metadata.distributions(path=[entry]), key=lambda d: str(d._path), ): name = distribution.metadata["name"] version = distribution.metadata["version"] package = Package(name, version, version) package.description = distribution.metadata.get("summary", "") if package.name in seen: continue seen.add(package.name) repo.add_package(package) path = Path(str(distribution._path)) is_standard_package = True try: path.relative_to(env.site_packages) except ValueError: is_standard_package = False if is_standard_package: continue src_path = env.path / "src" # A VCS dependency should have been installed # in the src directory. If not, it's a path dependency try: path.relative_to(src_path) from poetry.vcs.git import Git git = Git() revision = git.rev_parse("HEAD", src_path / package.name).strip() url = git.remote_url(src_path / package.name) package.source_type = "git" package.source_url = url package.source_reference = revision except ValueError: package.source_type = "directory" package.source_url = str(path.parent) return repo
def test_package_authors(): package = Package('foo', '0.1.0') package.authors.append('Sébastien Eustace <*****@*****.**>') assert package.author_name == 'Sébastien Eustace' assert package.author_email == '*****@*****.**' package.authors.insert(0, 'John Doe') assert package.author_name == 'John Doe' assert package.author_email is None
def test_package_authors(): package = Package("foo", "0.1.0") package.authors.append("Sébastien Eustace <*****@*****.**>") assert package.author_name == "Sébastien Eustace" assert package.author_email == "*****@*****.**" package.authors.insert(0, "John Doe") assert package.author_name == "John Doe" assert package.author_email is None
def find_packages( self, name, # type: str constraint=None, # type: Union[VersionConstraint, str, None] extras=None, # type: Union[list, None] allow_prereleases=False, # type: bool ): # type: (...) -> List[Package] """ Find packages on the remote server. """ if constraint is None: constraint = "*" if not isinstance(constraint, VersionConstraint): constraint = parse_constraint(constraint) if isinstance(constraint, VersionRange): if (constraint.max is not None and constraint.max.is_prerelease() or constraint.min is not None and constraint.min.is_prerelease()): allow_prereleases = True info = self.get_package_info(name) packages = [] for version, release in info["releases"].items(): if not release: # Bad release self._log( "No release information found for {}-{}, skipping".format( name, version), level="debug", ) continue package = Package(name, version) if package.is_prerelease() and not allow_prereleases: continue if not constraint or (constraint and constraint.allows(package.version)): if extras is not None: package.requires_extras = extras packages.append(package) self._log( "{} packages found for {} {}".format(len(packages), name, str(constraint)), level="debug", ) return packages
def test_package_authors_invalid(): package = Package("foo", "0.1.0") package.authors.insert(0, "<John Doe") with pytest.raises(ValueError) as e: package.author_name assert ( str(e.value) == "Invalid author string. Must be in the format: John Smith <*****@*****.**>" )
def test_package_url_category_optional(category, optional): package = Package("foo", "0.1.0") dependency = package.add_dependency( "poetry", constraint={ "url": "https://github.com/python-poetry/poetry/releases/download/1.0.5/poetry-1.0.5-linux.tar.gz", "optional": optional, }, category=category, ) assert dependency.category == category assert dependency.is_optional() == optional
def find_packages(self, name, # type: str constraint=None, # type: Union[Constraint, str, None] extras=None, # type: Union[list, None] allow_prereleases=False # type: bool ): # type: (...) -> List[Package] """ Find packages on the remote server. """ if constraint is not None and not isinstance(constraint, BaseConstraint): version_parser = VersionParser() constraint = version_parser.parse_constraints(constraint) info = self.get_package_info(name) packages = [] for version, release in info['releases'].items(): if not release: # Bad release self._log( 'No release information found for {}-{}, skipping'.format( name, version ), level='debug' ) continue package = Package(name, version) if package.is_prerelease() and not allow_prereleases: continue if ( not constraint or (constraint and constraint.matches(Constraint('=', version))) ): if extras is not None: package.requires_extras = extras packages.append(package) self._log( '{} packages found for {} {}'.format( len(packages), name, str(constraint) ), level='debug' ) return packages
def load(cls, venv): # type: (Venv) -> InstalledRepository """ Load installed packages. For now, it uses the pip "freeze" command. """ repo = cls() freeze_output = venv.run('pip', 'freeze') for line in freeze_output.split('\n'): if '==' in line: name, version = line.split('==') repo.add_package(Package(name, version, version)) return repo
def load(cls, env): # type: (Env) -> InstalledRepository """ Load installed packages. For now, it uses the pip "freeze" command. """ repo = cls() freeze_output = env.run("pip", "freeze") for line in freeze_output.split("\n"): if "==" in line: name, version = line.split("==") repo.add_package(Package(name, version, version)) return repo
def search(self, query, mode=0): results = [] search = {"name": query} if mode == self.SEARCH_FULLTEXT: search["summary"] = query client = ServerProxy("https://pypi.python.org/pypi") hits = client.search(search, "or") for hit in hits: result = Package(hit["name"], hit["version"], hit["version"]) result.description = to_str(hit["summary"]) results.append(result) return results
def search(self, query, mode=0): results = [] search = {'name': query} if mode == self.SEARCH_FULLTEXT: search['summary'] = query client = ServerProxy('https://pypi.python.org/pypi') hits = client.search(search, 'or') for hit in hits: result = Package(hit['name'], hit['version'], hit['version']) result.description = to_str(hit['summary']) results.append(result) return results