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

How to use pipx to install namespace package from private repo #635

Closed
taranlu-houzz opened this issue Feb 24, 2021 · 12 comments
Closed

How to use pipx to install namespace package from private repo #635

taranlu-houzz opened this issue Feb 24, 2021 · 12 comments

Comments

@taranlu-houzz
Copy link

Describe the bug
Not really a bug, but I couldn't find an incantation that worked for my use-case. I have a private repo served on our local network, and would like to use pipx to install a namespace package from it. I'm guessing that this is possible, since pipx uses pip internally, and I know that my repo works correctly because I use poetry to install packages from it frequently.

I have tried the following:

pipx install --index-url "http://<my index>:8885" my.special.namespace.package
pipx install --index-url "http://<my index>:8885/simple" my.special.namespace.package
pipx install --index-url "http://<my index>:8885/" my-special-namespace-package
pipx install --index-url "http://<my index>:8885/simple" my-special-namespace-package

Environment

  • macOS 10.14
  • pipx installed via brew
  • asdf installed Python, and set PIPX_DEFAULT_PYTHON
  • Private package repo on local network is served using pypiserver
  • The packages I have tried to install do contain cli entry points.
@itsayellow
Copy link
Contributor

itsayellow commented Feb 24, 2021

I'm not super-familiar with this flow so I tested on a PyPI package. This finally worked:

pipx install --index-url="https://pypi.org/simple" pylint

So for the index url, you do need the /simple at the end of it. That's one thing.

The other thing (I believe) for your my.special.namespace.package package to install is that the following url needs to be valid, you can check it on a web browser:

http://<my index>:8885/simple/my.special.namespace.package

(From my example, I can navigate to https://pypi.org/simple/pylint/ in my web browser and it comes up successfully.

@itsayellow
Copy link
Contributor

One snag may be that since you are using http:// and not https:// you need to tell pip that it is a "trusted host".
https://pip.pypa.io/en/stable/reference/pip/#cmdoption-trusted-host

You could do this with pip user or global settings, or on pipx's command line or with the --pip-args option to pipx install.

For pipx, I think it would be something like:

pipx install --pip-args='--trusted-host=http://<my index>:8885/' --index-url="http://<my index>:8885/simple"

Although I tend to forget the right way to do the --pip-args syntax, so you might need to modify that.

@itsayellow
Copy link
Contributor

https://pip.pypa.io/en/stable/user_guide/?highlight=appdata#config-file
If you search that for trusted-host you'll find a section showing how to modify a pip config file.

@itsayellow
Copy link
Contributor

Better --pip-args guidance:
#204 (comment)

@taranlu-houzz
Copy link
Author

@itsayellow Thanks for the info. Since my packages rely on both internal packages and packages from the main pypi, I ended up needing to use --extra-index-url to get what I wanted (that way, pip falls back to regular pypi):

pipx install <my.special.package> --pip-args="--extra-index-url=http://<internal ip>:8885 --trusted-host=<internal ip>"

@uranusjr
Copy link
Member

Note that using --extra-index-url to obtain non-PyPI packages has security implications (many info available by searching for the flag + "security"). This may or may not be an acceptable tradeoff depending on your scenario.

@taranlu-houzz
Copy link
Author

@uranusjr Aside from packages not being what one expects (shadowing) or containing malicious code if the extra index was not my own, are there other security implications you are suggesting since I own and control this repo?

@uranusjr
Copy link
Member

Unless you also own the name on PyPI, people can shadow you on there as well.

@taranlu-houzz
Copy link
Author

@uranusjr Interesting point. Do you know if there is a way to specifically set the index search order so that my private index is used first, and regular pypi is only used as a fallback?

@taranlu-houzz
Copy link
Author

I suppose maybe something like this:

pipx install <my.special.package> --pip-args="--index-url=http://<internal ip>:8885 --trusted-host=<internal ip> --extra-index-url=<url for main pypi>"

@uranusjr
Copy link
Member

I suppose maybe something like this:

It does not help, indexes don’t have priorities because that’s not what multiple indexes are designed to solve. More context:

pypa/pip#9612
pypa/pip#9647
https://discuss.python.org/t/addressing-dependency-version-confusion-exploit-chain/7143
https://discuss.python.org/t/pypi-as-a-project-repository-vs-name-registry-a-k-a-pypi-namesquatting-e-g-for-fedora-packages/4045

@smprather
Copy link

I created this script to enable use of an internal PyPI server (pypiserver instance) and my group's shared unix drive space. However, creating the wrapper was awkward because I'm not allowed to give the --index-url unless it is actually needed. Wouldn't it make sense to enable pipx to accomplish the function of this wrapper using just env vars (PIPX_INDEX_URL, PIPX_PIP_ARGS)?

#!/usr/bin/python3                           
import os                                    
import sys                                   
                                             
my_group_home = "/proj/my_group_space"       
my_group_pyenv = f"{my_group_home}/envs/my_group_python3.11"
my_group_pipx_path = f"{my_group_pyenv}/bin/pipx"
os.environ["PIPX_HOME"] = f"{my_group_home}/envs/pipx"
os.environ["PIPX_BIN_DIR"] = f"{my_group_home}/bin"
os.environ["PIPX_DEFAULT_PYTHON"] = f"{my_group_pyenv}/bin/python3"
if len({"install", "upgrade"} & set(sys.argv[1:3])) > 0:
    cmd = (                                  
        [my_group_pipx_path]                 
        + sys.argv[1:]                       
        + [                                  
            "--index-url",                   
            "http://my.internal.pypi:8080/simple/",
            "--pip-args",
            "--trusted-host my.internal.pypi",
        ]             
    )                 
    print(*cmd)       
    os.execv(my_group_pipx_path, cmd)                                                                                                                                              
else:                                        
    cmd = [my_group_pipx_path] + sys.argv[1:]
    os.execv(my_group_pipx_path, cmd)        

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants