Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CLI flag for rendering non-VCS files as relative paths. #702

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions piptools/scripts/compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,15 @@ class PipCommand(Command):
help="Generate pip 8 style hashes in the resulting requirements file.")
@click.option('--max-rounds', default=10,
help="Maximum number of rounds before resolving the requirements aborts.")
@click.option('--files-relative-to',
help="Render file:// requirements relative to this path. "
"By default, absolute paths are used.",
type=click.Path(resolve_path=True))
@click.argument('src_files', nargs=-1, type=click.Path(exists=True, allow_dash=True))
def cli(verbose, dry_run, pre, rebuild, find_links, index_url, extra_index_url,
cert, client_cert, trusted_host, header, index, emit_trusted_host, annotate,
upgrade, upgrade_packages, output_file, allow_unsafe, generate_hashes,
src_files, max_rounds):
src_files, max_rounds, files_relative_to):
"""Compiles requirements.txt from requirements.in specs."""
log.verbose = verbose

Expand Down Expand Up @@ -241,7 +245,8 @@ def cli(verbose, dry_run, pre, rebuild, find_links, index_url, extra_index_url,
default_index_url=repository.DEFAULT_INDEX_URL,
index_urls=repository.finder.index_urls,
trusted_hosts=pip_options.trusted_hosts,
format_control=repository.finder.format_control)
format_control=repository.finder.format_control,
files_relative_to=files_relative_to)
writer.write(results=results,
unsafe_requirements=resolver.unsafe_constraints,
reverse_dependencies=reverse_dependencies,
Expand Down
23 changes: 20 additions & 3 deletions piptools/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
from collections import OrderedDict
from contextlib import contextmanager

from ._compat import install_req_from_line
from ._compat import install_req_from_line, is_file_url, url_to_path

from .click import style
import six.moves.urllib.request as urllib_request
import six.moves.urllib.parse as urllib_parse


UNSAFE_PACKAGES = {'setuptools', 'distribute', 'pip'}
Expand Down Expand Up @@ -53,13 +55,22 @@ def make_install_requirement(name, version, extras, constraint=False):
constraint=constraint)


def format_requirement(ireq, marker=None):
def format_requirement(ireq, marker=None, files_relative_to=None):
"""
Generic formatter for pretty printing InstallRequirements to the terminal
in a less verbose way than using its `__str__` method.

By default, file:// urls are rendered using absolute paths. If
``files_relative_to`` is specified, file paths for are rendered relative to
the given path. This is used when rendering outputs from pip-compile.
"""
if ireq.editable:
line = '-e {}'.format(ireq.link)
link = ireq.link
if is_file_url(ireq.link) and files_relative_to is not None:
target = os.path.relpath(link.path, start=files_relative_to)
else:
target = ireq.link
line = '-e {}'.format(target)
else:
line = str(ireq.req).lower()

Expand Down Expand Up @@ -249,3 +260,9 @@ def temp_environ():
finally:
os.environ.clear()
os.environ.update(environ)


def path_to_url(path):
"""Render a filesystem path as a URL.
"""
return urllib_parse.urljoin('file:', urllib_request.pathname2url(path))
6 changes: 4 additions & 2 deletions piptools/writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
class OutputWriter(object):
def __init__(self, src_files, dst_file, dry_run, emit_header, emit_index,
emit_trusted_host, annotate, generate_hashes,
default_index_url, index_urls, trusted_hosts, format_control):
default_index_url, index_urls, trusted_hosts, format_control,
files_relative_to):
self.src_files = src_files
self.dst_file = dst_file
self.dry_run = dry_run
Expand All @@ -24,6 +25,7 @@ def __init__(self, src_files, dst_file, dry_run, emit_header, emit_index,
self.index_urls = index_urls
self.trusted_hosts = trusted_hosts
self.format_control = format_control
self.files_relative_to = files_relative_to

def _sort_key(self, ireq):
return (not ireq.editable, str(ireq.req).lower())
Expand Down Expand Up @@ -130,7 +132,7 @@ def write(self, results, unsafe_requirements, reverse_dependencies,
f.write(os.linesep.encode('utf-8'))

def _format_requirement(self, ireq, reverse_dependencies, primary_packages, marker=None, hashes=None):
line = format_requirement(ireq, marker=marker)
line = format_requirement(ireq, marker=marker, files_relative_to=self.files_relative_to)

ireq_hashes = (hashes if hashes is not None else {}).get(ireq)
if ireq_hashes:
Expand Down
3 changes: 2 additions & 1 deletion tests/test_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ def writer():
generate_hashes=False,
default_index_url=None, index_urls=[],
trusted_hosts=[],
format_control=FormatControl(set(), set()))
format_control=FormatControl(set(), set()),
files_relative_to=None)


def test_format_requirement_annotation_editable(from_editable, writer):
Expand Down