pip-tools icon indicating copy to clipboard operation
pip-tools copied to clipboard

pip-compile absolute links when given relative path

Open ColtonProvias opened this issue 8 years ago • 55 comments

requirements.in:

-e .
-e ./sqlalchemy_jsonapi

compiles to:

-e file:///Users/coltonprovias/MyProject
-e file:///Users/coltonprovias/MyProject/sqlalchemy_jsonapi

It should compile to

-e .
-e ./sqlalchemy_jsonapi

It's not really useful for me to provide a requirements.txt file then to anybody unless they use a Mac and have the same name as me. Although if that person does exist, I would like to meet them.

ColtonProvias avatar Sep 17 '15 02:09 ColtonProvias

I ran into the same issue today. Why are relative paths are expanded?

cdwilson avatar Dec 06 '15 17:12 cdwilson

This has affected me too as I'm trying to install packages which are submodules of my project. It seems the issues arises here: https://github.com/pypa/pip/blob/develop/pip/req/req_install.py#L1131

I suspect it is hard to avoid as pip-tools uses the pip library and the pip library has no reason to keep a relative path around. It wants to deal with absolute paths.

Which means that it is unlikely that we'd get the pip library changed to help us so which suggests that we'd have to get the output from the pip library and go back and make any paths relative again which is an option but not incredibly desirable as it might be hard to know exactly when to do it and when not to.

Personally, I'm going to try switching from using submodules and relative paths to having git+git:// paths in my requirements.in file but at the same time it seems very reasonable to try to fix this as it makes little sense to have absolute paths in a requirements.txt file when there is little chance that the paths in different development environments or the production environment is going to be the same. That is certainly what affects me. Of course, the requirements.txt should also be in git so it should be possible to pip-compile and then edit the requirements.txt before committing it.

michaeljones avatar Jan 10 '16 18:01 michaeljones

Looks like https://github.com/nvie/pip-tools/issues/325 is related

HelloGrayson avatar Apr 05 '16 23:04 HelloGrayson

I've been planning to move all of the requirements handling across all of our repos to using pip-tools and just realized it had this issue, which may completely shelve that plan. This is a pretty significant problem.

jredwards avatar Feb 18 '17 23:02 jredwards

So the core of this comes down to this function here, inside pip. I don't think it would be easy to fix in pip itself, so I will see if I can manipulate the result while outputting it to the file by making the result relative.

orf avatar May 12 '17 09:05 orf

the relative paths should actually use file:foo/bar so that the #egg=spam fragment could be appended. Unfortunately this breaks in pip-compile, as pip-compile tries reading foo/bar/setup.py after setting foo/bar as the current directory!

ztane avatar Sep 12 '18 13:09 ztane

as for why #egg=spam would be needed, is for pip dependency resolver to find out what abstract requirement is provided by the said file link! Otherwise it is going to attempt to download spam from Warehouse!

ztane avatar Sep 12 '18 13:09 ztane

If your parrot is a git submodule, this works well: -e git+path/to/dead/parrot#egg=parrot.

rollcat avatar Sep 14 '18 06:09 rollcat

@rollcat almost works... except that we merged 2 repos so it is a slug and hardly speaks.

ztane avatar Sep 14 '18 09:09 ztane

I took another stab at trying to fix this in https://github.com/jazzband/pip-tools/pull/702.

ssanderson avatar Dec 18 '18 02:12 ssanderson

I've been using the following post-processing step to get around the problem: make_paths_relative.py < requirements.txt (script below)

#!/usr/bin/env python
import os
import re
import sys

pattern = re.compile(r"\s*-e\s+file://(?P<path>.*?)\n")
inputs = sys.stdin.readlines()
for line in inputs:
    match = pattern.match(line)
    if match:
        path = match.group("path")
        path = os.path.relpath(path)
        line = f"-e {path}\n"
    sys.stdout.write(line)

tillahoffmann avatar Feb 19 '19 11:02 tillahoffmann

A(nother) hacky solution, in requirements.in:

-e file:relative/path/to/my_package

then to compile:

pip-compile -q -o - | sed s:///::g > requirements.txt

leontrolski avatar Apr 24 '19 13:04 leontrolski

Ran into this issue as well. If I modify all my -e src/foo links to -e file:src/foo#egg=foo then the compiled requirements file drops out the same -e file:src/foo#egg=foo and this works as expected. Quite a lot more verbose than necessary though. The egg on the end is required, or the sed script above in https://github.com/jazzband/pip-tools/issues/204#issuecomment-486242541 otherwise the later pip install -r will not properly find the "foo" project to satisfy the dependency lists of other projects depending on "foo".

mmerickel avatar Nov 05 '19 22:11 mmerickel

@mmerickel

Ran into this issue as well. If I modify all my -e src/foo links to -e file:src/foo#egg=foo then the compiled requirements file drops out the same -e file:src/foo#egg=foo and this works as expected.

That's a nice workaround!

atugushev avatar Nov 07 '19 06:11 atugushev

I don't see it mentioned specifically here, but I've had the same issue with --find-links ./local_src. I want pip to look for packages within a directory as part of the project, but pip-compile translates that into an absolute path with './local_src' tacked on to the end.

tisdall avatar Dec 11 '19 15:12 tisdall

@tisdall you could try --find-links file:./local_src. It keeps the relative path.

atugushev avatar Dec 11 '19 15:12 atugushev

@atugushev thanks! Strangely when I tried it I had both relative and the original full path until I completely deleted the 'requirements.txt' and then recompiled.

tisdall avatar Dec 11 '19 15:12 tisdall

@tisdall looks like a bug. Could you file an issue?

atugushev avatar Dec 11 '19 16:12 atugushev

+1 We are also dealing with this issue

cackovic avatar Dec 20 '19 23:12 cackovic

I've pinned the issue to bring more attention to the most wanted feature based on reactions.

atugushev avatar Mar 20 '20 16:03 atugushev

I'm happy to work on this and other path-sanity tasks, but would like some discussion re: #1067 before diving in.

AndydeCleyre avatar Mar 26 '20 04:03 AndydeCleyre

Just ran into this issue today when migrating to pip-tools while still listing requirements inside setup.py, blocking our implementation.

rtibbles avatar Apr 17 '20 16:04 rtibbles

I was trying to figure out the proper syntaxes supported for paths, by reading here.

That indicates either of the following are acceptable:

[-e] [<vcs>+]file://<path>[#egg=<name>]
[-e] <name> @ file://<path>

Notes on that:

  • Be careful, if you accidentally add a slash to a relative path (file:///.) you'll be trying to install a whole lot more than you bargained for!
  • It seems relative paths here aren't supported by file://; if I have file://.#egg=pip-tools and try pip install -r requirements.in, it'll fail with:
ValueError: non-local file URIs are not supported on this platform: 'file://.'
  • Using the undocumented (at least at the above link) syntax file:. will work with the first syntax, but not the second.
  • Using git+file:. will not work.
  • git+file:// will not work with the second syntax.

So my understanding is now that these are the appropriate syntaxes for local paths:

[-e] [<vcs>+]file://<absolute>[#egg=<name>]
[-e] <name> @ file://<absolute>
[-e] file:<relative>[#egg=<name>]

Q1: Is this an acceptable standard for this project?

I haven't begun to look at the setup.py syntaxes.

Q2: Setting aside setup.py for the moment, if we abide by the above potential standard, what doesn't work?

Q3: I also want to note and check for agreement here that we should ensure the relative paths output are reformulated to be relative to the output file, if output "file" is not stdout.

AndydeCleyre avatar Apr 18 '20 21:04 AndydeCleyre

Any news regarding this issue. Also ran into this "problem". Cheers.

zuckerruebe avatar Jul 02 '20 11:07 zuckerruebe

Hello @zuckerruebe,

Thanks for pinging! As far as I know, nobody works on this issue at the moment. In the meantime, you might use these workarounds:

  1. https://github.com/jazzband/pip-tools/issues/204#issuecomment-564597799
  2. https://github.com/jazzband/pip-tools/issues/204#issuecomment-550051424

atugushev avatar Jul 02 '20 11:07 atugushev

@zuckerruebe @atugushev and anyone else, can you provide any feedback for Q1, Q2, Q3 at the end of my last comment (jump to "So my understanding" above the last code block)?

AndydeCleyre avatar Jul 03 '20 17:07 AndydeCleyre

Q1: Is this an acceptable standard for this project?

IMO Instead

[-e] file:<relative>[#egg=<name>]

it should be:

[-e] <relative>[#egg=<name>]

AFAIK file:./relative/path is not a standard (more like a workaround) and we shouldn't rely on it in a long prospect future. I swear I saw a discussion about it on pip tracker, but can't find anymore :(

Q2: Setting aside setup.py for the moment, if we abide by the above potential standard, what doesn't work?

I think I'm not following the question here. Could you elaborate?

Q3: I also want to note and check for agreement here that we should ensure the relative paths output are reformulated to be relative to the output file, if output "file" is not stdout.

Yes, makes sense to me.

UPDATE: found a discussion about file:./relative/path https://github.com/pypa/packaging/issues/120

atugushev avatar Jul 18 '20 03:07 atugushev

Thanks @atugushev!


Q2

I'm asking: if users use one of the following syntaxes:

[-e] [<vcs>+]file://<absolute>[#egg=<name>]
[-e] <name> @ file://<absolute>
[-e] file:<relative>[#egg=<name>]

what exactly goes wrong, as the most basic case of the issue (compiling relpaths to relpaths) doesn't seem to be a problem? I notice two things to start with:

  • only compiles if done from the same directory as the in-file
  • the relpath is preserved literally, anchored to the path of the in-file, instead of the out-file

Q1

After reading the pypa/packaging issue you linked (and spidering out from there), it looks like we're waiting for some things to shake out at pypa/pip and pypa/packaging:

  • this issue will not be thoroughly resolved until at least:
    • pypa/pip#6658
    • pypa/packaging#120
  • we should also be interested to track:
  • you are right, file:./relpath is an unreliable non-standard, not to be encouraged (but it is tested for in pip's test_basic_install_relative_directory)
  • but [-e] <relative>[#egg=<name>] is not great either. From pip#6658 (comment):

    [simply ./some/path] wouldn't be acceptable per PEP 508, so it would be hard to justify supporting much less get it working across all tools.

  • I think we're waiting on better support for name @ <relpath>, and generally stronger consensus on proper spec -- relative paths are currently resolved based on different origins depending on tool/codepath...

We may eventually be able to focus on:

[-e] <name> @ [git+file://]<relative-or-absolute>[@<tag-ish>]

AndydeCleyre avatar Jul 19 '20 19:07 AndydeCleyre

I just want to reiterate for all the watchers that while we're still waiting on path syntaxes to settle upstream, much of the time, for now, you'll get what you want by using file:./relpath, such as -e file:..

AndydeCleyre avatar Feb 24 '21 22:02 AndydeCleyre

I welcome any and all testers to try #1329, and please let me know if you consider this issue fixed by its changes.

AndydeCleyre avatar Mar 18 '21 18:03 AndydeCleyre