def load(cls, path, create=True): """Create a new lockfile instance. :param project_path: Path to project root or lockfile :type project_path: str or :class:`pathlib.Path` :param str lockfile_name: Name of the lockfile in the project root directory :param pipfile_path: Path to the project pipfile :type pipfile_path: :class:`pathlib.Path` :returns: A new lockfile representing the supplied project paths :rtype: :class:`~requirementslib.models.lockfile.Lockfile` """ try: projectfile = cls.load_projectfile(path, create=create) except JSONDecodeError: path = os.path.abspath(path) path = Path( os.path.join(path, "Pipfile.lock") if os.path.isdir(path) else path ) formatted_path = path.as_posix() backup_path = "%s.bak" % formatted_path LockfileCorruptException.show(formatted_path, backup_path=backup_path) path.rename(backup_path) cls.load(formatted_path, create=True) lockfile_path = Path(projectfile.location) creation_args = { "projectfile": projectfile, "lockfile": projectfile.model, "newlines": projectfile.line_ending, "path": lockfile_path } return cls(**creation_args)
def formatted_path(self): if self.path: path = self.path if not isinstance(path, Path): path = Path(path) return path.as_posix() return
def get_name(self): loc = self.path or self.uri if loc: self._uri_scheme = "path" if self.path else "uri" name = None if self.link and self.link.egg_fragment: return self.link.egg_fragment elif self.link and self.link.is_wheel: from pip_shims import Wheel return Wheel(self.link.filename).name if (self._uri_scheme != "uri" and self.path and self.setup_path and self.setup_path.exists()): from setuptools.dist import distutils old_curdir = os.path.abspath(os.getcwd()) try: os.chdir(str(self.setup_path.parent)) dist = distutils.core.run_setup(self.setup_path.as_posix()) name = dist.get_name() except (FileNotFoundError, IOError) as e: dist = None except Exception as e: from pip_shims.shims import make_abstract_dist try: if not isinstance(Path, self.path): _path = Path(self.path) else: _path = self.path if self.editable: _ireq = pip_shims.shims.install_req_from_editable( _path.as_uri()) else: _ireq = pip_shims.shims.install_req_from_line( _path.as_posix()) dist = make_abstract_dist(_ireq).get_dist() name = dist.project_name except (TypeError, ValueError, AttributeError) as e: dist = None finally: os.chdir(old_curdir) hashed_loc = hashlib.sha256(loc.encode("utf-8")).hexdigest() hashed_name = hashed_loc[-7:] if not name or name == "UNKNOWN": self._has_hashed_name = True name = hashed_name if self.link and not self._has_hashed_name: self.link = create_link("{0}#egg={1}".format(self.link.url, name)) return name
def create(cls, base_dir, subdirectory=None, ireq=None, kwargs=None): if not base_dir or base_dir is None: return creation_kwargs = {"extra_kwargs": kwargs} if not isinstance(base_dir, Path): base_dir = Path(base_dir) creation_kwargs["base_dir"] = base_dir.as_posix() pyproject = base_dir.joinpath("pyproject.toml") if subdirectory is not None: base_dir = base_dir.joinpath(subdirectory) setup_py = base_dir.joinpath("setup.py") setup_cfg = base_dir.joinpath("setup.cfg") creation_kwargs["pyproject"] = pyproject creation_kwargs["setup_py"] = setup_py creation_kwargs["setup_cfg"] = setup_cfg if ireq: creation_kwargs["ireq"] = ireq return cls(**creation_kwargs)
def create(cls, base_dir, subdirectory=None, ireq=None, kwargs=None): # type: (AnyStr, Optional[AnyStr], Optional[InstallRequirement], Optional[Dict[AnyStr, AnyStr]]) -> Optional[SetupInfo] if not base_dir or base_dir is None: return creation_kwargs = {"extra_kwargs": kwargs} if not isinstance(base_dir, Path): base_dir = Path(base_dir) creation_kwargs["base_dir"] = base_dir.as_posix() pyproject = base_dir.joinpath("pyproject.toml") if subdirectory is not None: base_dir = base_dir.joinpath(subdirectory) setup_py = base_dir.joinpath("setup.py") setup_cfg = base_dir.joinpath("setup.cfg") creation_kwargs["pyproject"] = pyproject creation_kwargs["setup_py"] = setup_py creation_kwargs["setup_cfg"] = setup_cfg if ireq: creation_kwargs["ireq"] = ireq created = cls(**creation_kwargs) created.get_info() return created
def get_link_from_line(cls, line): """Parse link information from given requirement line. Return a 6-tuple: - `vcs_type` indicates the VCS to use (e.g. "git"), or None. - `prefer` is either "file", "path" or "uri", indicating how the information should be used in later stages. - `relpath` is the relative path to use when recording the dependency, instead of the absolute path/URI used to perform installation. This can be None (to prefer the absolute path or URI). - `path` is the absolute file path to the package. This will always use forward slashes. Can be None if the line is a remote URI. - `uri` is the absolute URI to the package. Can be None if the line is not a URI. - `link` is an instance of :class:`pip._internal.index.Link`, representing a URI parse result based on the value of `uri`. This function is provided to deal with edge cases concerning URIs without a valid netloc. Those URIs are problematic to a straight ``urlsplit` call because they cannot be reliably reconstructed with ``urlunsplit`` due to a bug in the standard library: >>> from urllib.parse import urlsplit, urlunsplit >>> urlunsplit(urlsplit('git+file:///this/breaks')) 'git+file:/this/breaks' >>> urlunsplit(urlsplit('file:///this/works')) 'file:///this/works' See `https://bugs.python.org/issue23505#msg277350`. """ # Git allows `[email protected]...` lines that are not really URIs. # Add "ssh://" so we can parse correctly, and restore afterwards. fixed_line = add_ssh_scheme_to_git_uri(line) added_ssh_scheme = fixed_line != line # We can assume a lot of things if this is a local filesystem path. if "://" not in fixed_line: p = Path(fixed_line).absolute() path = p.as_posix() uri = p.as_uri() link = create_link(uri) try: relpath = get_converted_relative_path(path) except ValueError: relpath = None return LinkInfo(None, "path", relpath, path, uri, link) # This is an URI. We'll need to perform some elaborated parsing. parsed_url = urllib_parse.urlsplit(fixed_line) original_url = parsed_url._replace() if added_ssh_scheme and ':' in parsed_url.netloc: original_netloc, original_path_start = parsed_url.netloc.rsplit( ':', 1) uri_path = '/{0}{1}'.format(original_path_start, parsed_url.path) parsed_url = original_url._replace(netloc=original_netloc, path=uri_path) # Split the VCS part out if needed. original_scheme = parsed_url.scheme if "+" in original_scheme: vcs_type, scheme = original_scheme.split("+", 1) parsed_url = parsed_url._replace(scheme=scheme) prefer = "uri" else: vcs_type = None prefer = "file" if parsed_url.scheme == "file" and parsed_url.path: # This is a "file://" URI. Use url_to_path and path_to_url to # ensure the path is absolute. Also we need to build relpath. path = Path(url_to_path( urllib_parse.urlunsplit(parsed_url))).as_posix() try: relpath = get_converted_relative_path(path) except ValueError: relpath = None uri = path_to_url(path) else: # This is a remote URI. Simply use it. path = None relpath = None # Cut the fragment, but otherwise this is fixed_line. uri = urllib_parse.urlunsplit( parsed_url._replace(scheme=original_scheme, fragment="")) if added_ssh_scheme: original_uri = urllib_parse.urlunsplit( original_url._replace(scheme=original_scheme, fragment="")) uri = strip_ssh_from_git_uri(original_uri) # Re-attach VCS prefix to build a Link. link = create_link( urllib_parse.urlunsplit( parsed_url._replace(scheme=original_scheme))) return LinkInfo(vcs_type, prefer, relpath, path, uri, link)
class Lockfile(plette.lockfiles.Lockfile): def __init__(self, *args, **kwargs): path = kwargs.pop("path", None) self._requirements = kwargs.pop("requirements", []) self._dev_requirements = kwargs.pop("dev_requirements", []) self.path = Path(path) if path else None self.newlines = u"\n" super(Lockfile, self).__init__(*args, **kwargs) @classmethod def load(cls, path): if not path: path = os.curdir path = Path(path).absolute() if path.is_dir(): path = path / "Pipfile.lock" elif path.name == "Pipfile": path = path.parent / "Pipfile.lock" if not path.exists(): raise OSError("Path does not exist: %s" % path) return cls.create(path.parent, lockfile_name=path.name) @classmethod def create(cls, project_path, lockfile_name="Pipfile.lock"): """Create a new lockfile instance :param project_path: Path to project root :type project_path: str or :class:`~pathlib.Path` :returns: List[:class:`~requirementslib.Requirement`] objects """ if not isinstance(project_path, Path): project_path = Path(project_path) lockfile_path = project_path / lockfile_name with lockfile_path.open(encoding="utf-8") as f: lockfile = super(Lockfile, cls).load(f) lockfile.newlines = preferred_newlines(f) lockfile.path = lockfile_path return lockfile def get_requirements(self, dev=False): section = self.develop if dev else self.default for k in section.keys(): yield Requirement.from_pipfile(k, section[k]._data) @property def dev_requirements(self): if not self._dev_requirements: self._dev_requirements = list(self.get_requirements(dev=True)) return self._dev_requirements @property def requirements(self): if not self._requirements: self._requirements = list(self.get_requirements(dev=False)) return self._requirements @property def dev_requirements_list(self): return [{name: entry._data} for name, entry in self.develop.items()] @property def requirements_list(self): return [{name: entry._data} for name, entry in self.develop.items()] def write(self): open_kwargs = {"newline": self.newlines} with atomic_open_for_write(self.path.as_posix(), **open_kwargs) as f: super(Lockfile, self).dump(f, encoding="utf-8") def as_requirements(self, include_hashes=False, dev=False): """Returns a list of requirements in pip-style format""" lines = [] section = self.dev_requirements if dev else self.requirements for req in section: r = req.as_line() if not include_hashes: r = r.split("--hash", 1)[0] lines.append(r.strip()) return lines