def from_pipfile(cls, name, pipfile): creation_args = {} pipfile_keys = [ k for k in ("ref", "vcs", "subdirectory", "path", "editable", "file", "uri", "extras") + VCS_LIST if k in pipfile ] for key in pipfile_keys: if key == "extras": extras = pipfile.get(key, None) if extras: pipfile[key] = sorted( dedup([extra.lower() for extra in extras])) if key in VCS_LIST: creation_args["vcs"] = key target = pipfile.get(key) drive, path = os.path.splitdrive(target) if not drive and not os.path.exists(target) and ( is_valid_url(target) or is_file_url(target) or target.startswith('git@')): creation_args["uri"] = target else: creation_args["path"] = target if os.path.isabs(target): creation_args["uri"] = path_to_url(target) else: creation_args[key] = pipfile.get(key) creation_args["name"] = name return cls(**creation_args)
def from_pipfile(cls, name, pipfile): creation_args = {} pipfile_keys = [ k for k in ("ref", "vcs", "subdirectory", "path", "editable", "file", "uri", "extras") + VCS_LIST if k in pipfile ] for key in pipfile_keys: if key == "extras": extras = pipfile.get(key, None) if extras: pipfile[key] = sorted( dedup([extra.lower() for extra in extras])) if key in VCS_LIST: creation_args["vcs"] = key composed_uri = add_ssh_scheme_to_git_uri("{0}+{1}".format( key, pipfile.get(key))).split("+", 1)[1] url_keys = [pipfile.get(key), composed_uri] is_url = any( validity_fn(url_key) for url_key in url_keys for validity_fn in [is_valid_url, is_file_url]) target_key = "uri" if is_url else "path" creation_args[target_key] = pipfile.get(key) else: creation_args[key] = pipfile.get(key) creation_args["name"] = name return cls(**creation_args)
def parse_extras(extras_str): # type: (AnyStr) -> List[AnyStr] """ Turn a string of extras into a parsed extras list """ from pkg_resources import Requirement extras = Requirement.parse("fakepkg{0}".format( extras_to_string(extras_str))).extras return sorted(dedup([extra.lower() for extra in extras]))
def _sources_as_lines(sources): source_lines = list( dedup( itertools.chain( itertools.chain.from_iterable( _single_source_as_line(source, False) for source in sources[:1]), itertools.chain.from_iterable( _single_source_as_line(source, True) for source in sources[1:]), ))) return source_lines
def cleanup_pyspecs(specs, joiner="or"): if isinstance(specs, six.string_types): specs = set([_format_pyspec(specs)]) else: specs = {_format_pyspec(spec) for spec in specs} # for != operator we want to group by version # if all are consecutive, join as a list results = set() for op, versions in _group_by_op(tuple(specs)): versions = [version[1] for version in versions] versions = sorted(dedup(versions)) # if we are doing an or operation, we need to use the min for >= # this way OR(>=2.6, >=2.7, >=3.6) picks >=2.6 # if we do an AND operation we need to use MAX to be more selective if op in (">", ">="): if joiner == "or": results.add((op, _format_version(min(versions)))) else: results.add((op, _format_version(max(versions)))) # we use inverse logic here so we will take the max value if we are # using OR but the min value if we are using AND elif op in ("<=", "<"): if joiner == "or": results.add((op, _format_version(max(versions)))) else: results.add((op, _format_version(min(versions)))) # leave these the same no matter what operator we use elif op in ("!=", "==", "~="): version_list = sorted( "{0}".format(_format_version(version)) for version in versions ) version = ", ".join(version_list) if len(version_list) == 1: results.add((op, version)) elif op == "!=": results.add(("not in", version)) elif op == "==": results.add(("in", version)) else: specifier = SpecifierSet( ",".join(sorted("{0}{1}".format(op, v) for v in version_list)) )._specs for s in specifier: results.add((s._spec[0], s._spec[1])) else: if len(version) == 1: results.add((op, version)) else: specifier = SpecifierSet("{0}".format(version))._specs for s in specifier: results.add((s._spec[0], s._spec[1])) return sorted(results, key=operator.itemgetter(1))
def cleanup_pyspecs(specs, joiner="or"): specs = normalize_specifier_set(specs) # for != operator we want to group by version # if all are consecutive, join as a list results = {} translation_map = { # if we are doing an or operation, we need to use the min for >= # this way OR(>=2.6, >=2.7, >=3.6) picks >=2.6 # if we do an AND operation we need to use MAX to be more selective (">", ">="): { "or": lambda x: _format_version(min(x)), "and": lambda x: _format_version(max(x)), }, # we use inverse logic here so we will take the max value if we are # using OR but the min value if we are using AND ("<", "<="): { "or": lambda x: _format_version(max(x)), "and": lambda x: _format_version(min(x)), }, # leave these the same no matter what operator we use ("!=", "==", "~=", "==="): { "or": get_sorted_version_string, "and": get_sorted_version_string, }, } op_translations = { "!=": lambda x: "not in" if len(x) > 1 else "!=", "==": lambda x: "in" if len(x) > 1 else "==", } translation_keys = list(translation_map.keys()) for op_and_version_type, versions in _group_by_op(tuple(specs)): op = op_and_version_type[0] versions = [version[1] for version in versions] versions = sorted(dedup(versions)) op_key = next(iter(k for k in translation_keys if op in k), None) version_value = versions if op_key is not None: version_value = translation_map[op_key][joiner](versions) if op in op_translations: op = op_translations[op](versions) results[(op, op_and_version_type[1])] = version_value return sorted([(k[0], v) for k, v in results.items()], key=operator.itemgetter(1))
def from_pipfile(cls, name, pipfile): from .markers import PipenvMarkers _pipfile = {} if hasattr(pipfile, "keys"): _pipfile = dict(pipfile).copy() _pipfile["version"] = get_version(pipfile) vcs = first([vcs for vcs in VCS_LIST if vcs in _pipfile]) if vcs: _pipfile["vcs"] = vcs r = VCSRequirement.from_pipfile(name, pipfile) elif any(key in _pipfile for key in ["path", "file", "uri"]): r = FileRequirement.from_pipfile(name, pipfile) else: r = NamedRequirement.from_pipfile(name, pipfile) markers = PipenvMarkers.from_pipfile(name, _pipfile) req_markers = None if markers: markers = str(markers) req_markers = PackagingRequirement("fakepkg; {0}".format(markers)) r.req.marker = getattr(req_markers, "marker", None) r.req.specifier = SpecifierSet(_pipfile["version"]) extras = _pipfile.get("extras") r.req.extras = (sorted(dedup([extra.lower() for extra in extras])) if extras else []) args = { "name": r.name, "vcs": vcs, "req": r, "markers": markers, "extras": _pipfile.get("extras"), "editable": _pipfile.get("editable", False), "index": _pipfile.get("index"), } if any(key in _pipfile for key in ["hash", "hashes"]): args["hashes"] = _pipfile.get("hashes", [pipfile.get("hash")]) cls_inst = cls(**args) if cls_inst.is_named: cls_inst.req.req.line = cls_inst.as_line() return cls_inst
def _convert(file_instance, sources, section_names, hashes=False): """ :param file_instance: pipfile or lockfile instance :param hashes: bool :return: list """ sources_lines = _sources_as_lines(sources) requirements = [ Requirement.from_pipfile(key, entry._data) for key, entry in itertools.chain.from_iterable( file_instance.get(name, {}).items() for name in section_names) ] if hashes: hashes = all(r.is_named for r in requirements) requirement_lines = sorted( dedup( _requirement_as_line(requirement, hashes) for requirement in requirements)) return sources_lines + [''] + requirement_lines
def from_line(cls, line): from pip_shims import InstallRequirement if isinstance(line, InstallRequirement): line = format_requirement(line) hashes = None if "--hash=" in line: hashes = line.split(" --hash=") line, hashes = hashes[0], hashes[1:] editable = line.startswith("-e ") line = line.split(" ", 1)[1] if editable else line line, markers = split_markers_from_line(line) line, extras = _strip_extras(line) specifiers = '' if extras: extras = parse_extras(extras) line = line.strip('"').strip("'").strip() line_with_prefix = "-e {0}".format(line) if editable else line vcs = None # Installable local files and installable non-vcs urls are handled # as files, generally speaking line_is_vcs = is_vcs(line) if is_installable_file(line) or ( (is_file_url(line) or is_valid_url(line)) and not line_is_vcs): r = FileRequirement.from_line(line_with_prefix) elif line_is_vcs: r = VCSRequirement.from_line(line_with_prefix, extras=extras) vcs = r.vcs elif line == "." and not is_installable_file(line): raise RequirementError( "Error parsing requirement %s -- are you sure it is installable?" % line) else: specs = "!=<>~" spec_matches = set(specs) & set(line) version = None name = line if spec_matches: spec_idx = min((line.index(match) for match in spec_matches)) name = line[:spec_idx] version = line[spec_idx:] specifiers = version if not extras: name, extras = _strip_extras(name) if extras: extras = parse_extras(extras) if version: name = "{0}{1}".format(name, version) r = NamedRequirement.from_line(line) req_markers = None if markers: req_markers = PackagingRequirement("fakepkg; {0}".format(markers)) r.req.marker = getattr(req_markers, "marker", None) r.req.local_file = getattr(r.req, "local_file", False) name = getattr(r.req, "name", None) if not name: name = getattr(r.req, "project_name", None) r.req.name = name if not name: name = getattr(r.req, "key", None) if name: r.req.name = name args = { "name": r.name, "vcs": vcs, "req": r, "markers": markers, "editable": editable, } if extras: extras = sorted(dedup([extra.lower() for extra in extras])) args["extras"] = extras r.req.extras = extras r.extras = extras elif r.extras: args["extras"] = sorted( dedup([extra.lower() for extra in r.extras])) if hashes: args["hashes"] = hashes return cls(**args)
def _run_setup(self): # type: () -> "SystemPath" if not self.__class__ == SystemPath: return self new_instance = self path_order = new_instance.path_order[:] path_entries = self.paths.copy() if self.global_search and "PATH" in os.environ: path_order = path_order + os.environ["PATH"].split(os.pathsep) path_order = list(dedup(path_order)) path_instances = [ ensure_path(p.strip('"')) for p in path_order if not any( is_in_path(normalize_path(str(p)), normalize_path(shim)) for shim in SHIM_PATHS) ] path_entries.update({ p.as_posix(): PathEntry.create(path=p.absolute(), is_root=True, only_python=self.only_python) for p in path_instances }) new_instance = attr.evolve( new_instance, path_order=[p.as_posix() for p in path_instances], paths=path_entries, ) if os.name == "nt" and "windows" not in self.finders: new_instance = new_instance._setup_windows() #: slice in pyenv if self.check_for_pyenv() and "pyenv" not in self.finders: new_instance = new_instance._setup_pyenv() #: slice in asdf if self.check_for_asdf() and "asdf" not in self.finders: new_instance = new_instance._setup_asdf() venv = os.environ.get("VIRTUAL_ENV") if os.name == "nt": bin_dir = "Scripts" else: bin_dir = "bin" if venv and (new_instance.system or new_instance.global_search): p = ensure_path(venv) path_order = [(p / bin_dir).as_posix()] + new_instance.path_order new_instance = attr.evolve(new_instance, path_order=path_order) paths = new_instance.paths.copy() paths[p] = new_instance.get_path(p.joinpath(bin_dir)) new_instance = attr.evolve(new_instance, paths=paths) if new_instance.system: syspath = Path(sys.executable) syspath_bin = syspath.parent if syspath_bin.name != bin_dir and syspath_bin.joinpath( bin_dir).exists(): syspath_bin = syspath_bin / bin_dir path_order = [syspath_bin.as_posix()] + new_instance.path_order paths = new_instance.paths.copy() paths[syspath_bin] = PathEntry.create(path=syspath_bin, is_root=True, only_python=False) new_instance = attr.evolve(new_instance, path_order=path_order, paths=paths) return new_instance
def parse_extras(extras_str): """Turn a string of extras into a parsed extras list""" extras = Requirement.parse("fakepkg{0}".format( extras_to_string(extras_str))).extras return sorted(dedup([extra.lower() for extra in extras]))