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

Can't add package from private pypi repository using token access #4181

Closed
3 tasks done
shaunc opened this issue Jun 14, 2021 · 12 comments · Fixed by #9850
Closed
3 tasks done

Can't add package from private pypi repository using token access #4181

shaunc opened this issue Jun 14, 2021 · 12 comments · Fixed by #9850
Labels
area/auth Related to the authenticator and keyring area/sources Releated to package sources/indexes/repositories kind/bug Something isn't working as expected

Comments

@shaunc
Copy link

shaunc commented Jun 14, 2021

  • I am on the latest Poetry version.
  • I have searched the issues of this repo and believe that this is not a duplicate.
  • If an exception occurs when executing a command, I executed it again in debug mode (-vvv option).

Issue

I have added a private repository hosted in gitlab to poetry config:

poetry config repositories.machinelearning https://gl.factfiber.ai/api/v4/projects/8/packages/pypi/simple
poetry config pypi-token.machinelearning $TOKEN

However, I can't add a package from the repo:

poetry add dcache -vvv

[fails with auth error -- see stack trace below.]

However, I can add it using pip inside the virtual environment

poetry shell
pip install dcache --extra-index-url https://__token__:$TOKEN@gl.factfiber.ai/api/v4/projects/8/packages/pypi/simple

Stacktrace:

poetry add dcache -vvv
Using virtualenv: /home/shauncutts/.cache/pypoetry/virtualenvs/bt-features-BmwID7oW-py3.9

  Stack trace:

  10  ~/.cache/pypoetry/virtualenvs/bt-features-BmwID7oW-py3.9/lib/python3.9/site-packages/clikit/console_application.py:131 in run
       129│             parsed_args = resolved_command.args
       130│
     → 131│             status_code = command.handle(parsed_args, io)
       132│         except KeyboardInterrupt:
       133│             status_code = 1

   9  ~/.cache/pypoetry/virtualenvs/bt-features-BmwID7oW-py3.9/lib/python3.9/site-packages/clikit/api/command/command.py:120 in handle
       118│     def handle(self, args, io):  # type: (Args, IO) -> int
       119│         try:
     → 120│             status_code = self._do_handle(args, io)
       121│         except KeyboardInterrupt:
       122│             if io.is_debug():

   8  ~/.cache/pypoetry/virtualenvs/bt-features-BmwID7oW-py3.9/lib/python3.9/site-packages/clikit/api/command/command.py:171 in _do_handle
       169│         handler_method = self._config.handler_method
       170│
     → 171│         return getattr(handler, handler_method)(args, io, self)
       172│
       173│     def __repr__(self):  # type: () -> str

   7  ~/.cache/pypoetry/virtualenvs/bt-features-BmwID7oW-py3.9/lib/python3.9/site-packages/cleo/commands/command.py:92 in wrap_handle
        90│         self._command = command
        91│
     →  92│         return self.handle()
        93│
        94│     def handle(self):  # type: () -> Optional[int]

   6  ~/.cache/pypoetry/virtualenvs/bt-features-BmwID7oW-py3.9/lib/python3.9/site-packages/poetry/console/commands/add.py:106 in handle
       104│             return 0
       105│
     → 106│         requirements = self._determine_requirements(
       107│             packages,
       108│             allow_prereleases=self.option("allow-prereleases"),

   5  ~/.cache/pypoetry/virtualenvs/bt-features-BmwID7oW-py3.9/lib/python3.9/site-packages/poetry/console/commands/init.py:328 in _determine_
requirements
       326│             elif "version" not in requirement:
       327│                 # determine the best version automatically
     → 328│                 name, version = self._find_best_version_for_package(
       329│                     requirement["name"],
       330│                     allow_prereleases=allow_prereleases,

   4  ~/.cache/pypoetry/virtualenvs/bt-features-BmwID7oW-py3.9/lib/python3.9/site-packages/poetry/console/commands/init.py:361 in _find_best_version_for_package
       359│
       360│         selector = VersionSelector(self._get_pool())
     → 361│         package = selector.find_best_candidate(
       362│             name, required_version, allow_prereleases=allow_prereleases, source=source
       363│         )

   3  ~/.cache/pypoetry/virtualenvs/bt-features-BmwID7oW-py3.9/lib/python3.9/site-packages/poetry/version/version_selector.py:32 in find_best_candidate
       30│             },
       31│         )
     → 32│         candidates = self._pool.find_packages(dependency)
       33│         only_prereleases = all([c.version.is_prerelease() for c in candidates])
       34│

   2  ~/.cache/pypoetry/virtualenvs/bt-features-BmwID7oW-py3.9/lib/python3.9/site-packages/poetry/repositories/pool.py:165 in find_packages
       163│         packages = []
       164│         for repo in self._repositories:
     → 165│             packages += repo.find_packages(dependency)
       166│
       167│         return packages

   1  ~/.cache/pypoetry/virtualenvs/bt-features-BmwID7oW-py3.9/lib/python3.9/site-packages/poetry/repositories/legacy_repository.py:264 in find_packages
       262│             versions = self._cache.store("matches").get(key)
       263│         else:
     → 264│             page = self._get("/{}/".format(dependency.name.replace(".", "-")))
       265│             if page is None:
       266│                 return []

  RepositoryError

  401 Client Error: Unauthorized for url: https://gl.factfiber.ai/api/v4/projects/8/packages/pypi/simple/dcache/

  at ~/.cache/pypoetry/virtualenvs/bt-features-BmwID7oW-py3.9/lib/python3.9/site-packages/poetry/repositories/legacy_repository.py:393 in _get
      389│             if response.status_code == 404:
      390│                 return
      391│             response.raise_for_status()
      392│         except requests.HTTPError as e:
    → 393│             raise RepositoryError(e)
      394│
      395│         if response.status_code in (401, 403):
      396│             self._log(
      397│                 "Authorization error accessing {url}".format(url=response.url),

Note that these, also, didn't work:

poetry config http-basic.machinelearning $TOKEN "__token__"
poetry config http-basic.machinelearning "__token__" $TOKEN 
poetry config http-basic.machinelearning $TOKEN ""
poetry config http-basic.machinelearning "" $TOKEN 
@shaunc shaunc added kind/bug Something isn't working as expected status/triage This issue needs to be triaged labels Jun 14, 2021
@JamieMcKernanKaizen
Copy link

JamieMcKernanKaizen commented Nov 16, 2021

I am also having this issue. I am using:
poetry 1.1.11
Ubuntu 20.04.3 LTS

I've observed that when running poetry config http-basic.repo_name username password the password does get added to the built in Ubuntu password store (called Passwords and Keys). But it seems poetry can't access this and gives the 401 instead.

The current workaround I've found is to disable the keyring library, and edit the auth.toml myself with the username and password.

I can confirm using poetry 1.1.8 fixes the issue.

@e0lithic
Copy link

Facing the same issue.

For some reason, this issue doesn't persist in 1.0.0 but is present in all the latest 1.1.x versions.

@ralbertazzi
Copy link
Contributor

Can anyone reproduce it on Poetry 1.5 ?

@DariaPlotnikova
Copy link

@ralbertazzi hi. I faced kinda the same problem on 1.8.4, py3.11 with gemfury private repo. The most important is point 6 in "What I tried" block below.

What is my case

  • Local device linux with keyrings (poetry config keyring.enabled = true as well)
  • I have gemfury private repo (with token-based access only)
  • I want to configure pyproject to have additional supplemental source + a dependency with explicit source=my_source
  • I run the command poetry add my_lib==0.1.4 --source my_source -vvv and get 403:
(lib-server) dpw@dpw:~/ns/my_service poetry add my_lib==0.1.4 --source my_source -vvv

Loading configuration file /home/dpw/.config/pypoetry/config.toml
Loading configuration file /home/dpw/.config/pypoetry/auth.toml
Adding repository my_source (https://pypi.fury.io/my_source) and setting it as supplemental
Using virtualenv: /home/dpw/.pyenv/versions/3.11.9/envs/lib-server
Checking if keyring is available
[keyring:keyring.backend] Loading KWallet
[keyring:keyring.backend] Loading SecretService
[keyring:keyring.backend] Loading Windows
[keyring:keyring.backend] Loading chainer
[keyring:keyring.backend] Loading libsecret
[keyring:keyring.backend] Loading macOS
Using keyring backend 'SecretService Keyring'
Creating new session for pypi.fury.io
[urllib3:urllib3.connectionpool] Starting new HTTPS connection (1): pypi.fury.io:443
[urllib3:urllib3.connectionpool] https://pypi.fury.io:443 "GET /my_source/my_lib/ HTTP/11" 304 0
[filelock:filelock] Attempting to acquire lock 138215892927312 on /home/dpw/.cache/pypoetry/cache/repositories/my_source/_http/9/e/1/a/a/9e1aa63c395dfeb329a3132377c50d4750b7a3001fb8fbe3407dc940.lock
[filelock:filelock] Lock 138215892927312 acquired on /home/dpw/.cache/pypoetry/cache/repositories/my_source/_http/9/e/1/a/a/9e1aa63c395dfeb329a3132377c50d4750b7a3001fb8fbe3407dc940.lock
[filelock:filelock] Attempting to release lock 138215892927312 on /home/dpw/.cache/pypoetry/cache/repositories/my_source/_http/9/e/1/a/a/9e1aa63c395dfeb329a3132377c50d4750b7a3001fb8fbe3407dc940.lock
[filelock:filelock] Lock 138215892927312 released on /home/dpw/.cache/pypoetry/cache/repositories/my_source/_http/9/e/1/a/a/9e1aa63c395dfeb329a3132377c50d4750b7a3001fb8fbe3407dc940.lock
Source (my_source): 1 packages found for my_lib 0.1.4

Updating dependencies
Resolving dependencies...
   1: fact: my_service is 0.0.1
   1: derived: my_service
   1: fact: my_service depends on my_lib (0.1.4)
   1: fact: my_service depends on bson (^0.5.10)
   1: fact: my_service depends on ruff (^0.6.3)
   1: fact: my_service depends on mypy (^1.11.2)
   1: fact: my_service depends on pytest (^8.3.2)
   1: fact: my_service depends on coverage (^7.6.1)
   1: selecting my_service (0.0.1)
   1: derived: coverage (>=7.6.1,<8.0.0)
   1: derived: pytest (>=8.3.2,<9.0.0)
   1: derived: mypy (>=1.11.2,<2.0.0)
   1: derived: ruff (>=0.6.3,<0.7.0)
   1: derived: bson (>=0.5.10,<0.6.0)
   1: derived: my_lib (==0.1.4)
Source (my_source): 1 packages found for my_lib 0.1.4
   1: fact: my_lib (0.1.4) depends on pydantic (<2)
   1: fact: my_lib (0.1.4) depends on pyjwt (>=2.6.0,<3.0.0)
   1: fact: my_lib (0.1.4) depends on starlette (<0.36)
   1: selecting my_lib (0.1.4)
   1: derived: starlette (<0.36)
   1: derived: pyjwt (>=2.6.0,<3.0.0)
   1: derived: pydantic (<2)
   1: selecting coverage (7.6.7)
   1: fact: pytest (8.3.3) depends on iniconfig (*)
   1: fact: pytest (8.3.3) depends on packaging (*)
   1: fact: pytest (8.3.3) depends on pluggy (>=1.5,<2)
   1: fact: pytest (8.3.3) depends on colorama (*)
   1: selecting pytest (8.3.3)
   1: derived: colorama
   1: derived: pluggy (>=1.5,<2)
   1: derived: packaging
   1: derived: iniconfig
   1: fact: mypy (1.13.0) depends on typing-extensions (>=4.6.0)
   1: fact: mypy (1.13.0) depends on mypy-extensions (>=1.0.0)
   1: selecting mypy (1.13.0)
   1: derived: mypy-extensions (>=1.0.0)
   1: derived: typing-extensions (>=4.6.0)
   1: selecting ruff (0.6.9)
   1: fact: bson (0.5.10) depends on python-dateutil (>=2.4.0)
   1: fact: bson (0.5.10) depends on six (>=1.9.0)
   1: selecting bson (0.5.10)
   1: derived: six (>=1.9.0)
   1: derived: python-dateutil (>=2.4.0)
   1: fact: starlette (0.35.1) depends on anyio (>=3.4.0,<5)
   1: selecting starlette (0.35.1)
   1: derived: anyio (>=3.4.0,<5)
   1: selecting pyjwt (2.10.0)
   1: fact: pydantic (1.10.19) depends on typing-extensions (>=4.2.0)
   1: selecting pydantic (1.10.19)
   1: selecting pluggy (1.5.0)
   1: selecting packaging (24.2)
   1: selecting iniconfig (2.0.0)
   1: selecting mypy-extensions (1.0.0)
   1: selecting typing-extensions (4.12.2)
   1: selecting six (1.16.0)
   1: fact: python-dateutil (2.9.0.post0) depends on six (>=1.5)
   1: selecting python-dateutil (2.9.0.post0)
   1: fact: anyio (4.6.2.post1) depends on idna (>=2.8)
   1: fact: anyio (4.6.2.post1) depends on sniffio (>=1.1)
   1: selecting anyio (4.6.2.post1)
   1: derived: sniffio (>=1.1)
   1: derived: idna (>=2.8)
   1: selecting sniffio (1.3.1)
   1: selecting idna (3.10)
   1: selecting colorama (0.4.6)
   1: Version solving took 0.042 seconds.
   1: Tried 1 solutions.

Finding the necessary packages for the current system
Source (my_source): 1 packages found for my_lib 0.1.4

Package operations: 1 install, 0 updates, 0 removals, 15 skipped

  - Installing my_lib (0.1.4): Pending...
Source (my_source): Downloading: https://pypi.fury.io/my_source/-/VER_SOME_VERSION_HASH/my_lib-0.1.4-py3-none-any.whl#md5=40f7a6b41e90650244a8449b20b7a4db
[urllib3:urllib3.connectionpool] https://pypi.fury.io:443 "GET /my_source/-/VER_SOME_VERSION_HASH/my_lib-0.1.4-py3-none-any.whl HTTP/11" 200 7867
>>>>>>> RES 200 >>> {'User-Agent': 'poetry/1.8.4 CPython/3.11.9 Linux/6.8.0-48-generic', 'Accept-Encoding': 'Identity', 'Accept': '*/*', 'Connection': 'keep-alive', 'Authorization': 'Basic POETRY_GENERATED_AUTH_TOKEN'} https://pypi.fury.io/my_source/-/VER_SOME_VERSION_HASH/my_lib-0.1.4-py3-none-any.whl#md5=40f7a6b41e90650244a8449b20b7a4db
[filelock:filelock] Attempting to acquire lock 138215892942096 on /home/dpw/.cache/pypoetry/cache/repositories/my_source/_http/f/a/a/1/9/faa19d22d4591021c8183bf5044fc7c01b0bc268e35440781473a5d4.lock
[filelock:filelock] Lock 138215892942096 acquired on /home/dpw/.cache/pypoetry/cache/repositories/my_source/_http/f/a/a/1/9/faa19d22d4591021c8183bf5044fc7c01b0bc268e35440781473a5d4.lock
[filelock:filelock] Attempting to release lock 138215892942096 on /home/dpw/.cache/pypoetry/cache/repositories/my_source/_http/f/a/a/1/9/faa19d22d4591021c8183bf5044fc7c01b0bc268e35440781473a5d4.lock
[filelock:filelock] Lock 138215892942096 released on /home/dpw/.cache/pypoetry/cache/repositories/my_source/_http/f/a/a/1/9/faa19d22d4591021c8183bf5044fc7c01b0bc268e35440781473a5d4.lock
There are no known hash types for my_lib-0.1.4-py3-none-any.whl that are prioritised (known hash types: {'md5'})
Source (my_source): Downloading: https://pypi.fury.io/my_source/-/VER_SOME_VERSION_HASH/my_lib-0.1.4.tar.gz#md5=4c7a0c9c48a3d68984d1bec05639dc50
[urllib3:urllib3.connectionpool] https://pypi.fury.io:443 "GET /my_source/-/VER_SOME_VERSION_HASH/my_lib-0.1.4.tar.gz HTTP/11" 200 7124
>>>>>>> RES 200 >>> {'User-Agent': 'poetry/1.8.4 CPython/3.11.9 Linux/6.8.0-48-generic', 'Accept-Encoding': 'Identity', 'Accept': '*/*', 'Connection': 'keep-alive', 'Authorization': 'Basic POETRY_GENERATED_AUTH_TOKEN'} https://pypi.fury.io/my_source/-/VER_SOME_VERSION_HASH/my_lib-0.1.4.tar.gz#md5=4c7a0c9c48a3d68984d1bec05639dc50
[filelock:filelock] Attempting to acquire lock 138215892048848 on /home/dpw/.cache/pypoetry/cache/repositories/my_source/_http/d/f/a/6/d/dfa6d53cf2df66a53d779e8dfa4a21c6d51014acb69c81fb227a8204.lock
[filelock:filelock] Lock 138215892048848 acquired on /home/dpw/.cache/pypoetry/cache/repositories/my_source/_http/d/f/a/6/d/dfa6d53cf2df66a53d779e8dfa4a21c6d51014acb69c81fb227a8204.lock
[filelock:filelock] Attempting to release lock 138215892048848 on /home/dpw/.cache/pypoetry/cache/repositories/my_source/_http/d/f/a/6/d/dfa6d53cf2df66a53d779e8dfa4a21c6d51014acb69c81fb227a8204.lock
[filelock:filelock] Lock 138215892048848 released on /home/dpw/.cache/pypoetry/cache/repositories/my_source/_http/d/f/a/6/d/dfa6d53cf2df66a53d779e8dfa4a21c6d51014acb69c81fb227a8204.lock
There are no known hash types for my_lib-0.1.4.tar.gz that are prioritised (known hash types: {'md5'})
There are no known hash types for my_lib-0.1.4-py3-none-any.whl that are prioritised (known hash types: {'md5'})
Checking if keyring is available
Using keyring backend 'SecretService Keyring'
Creating new session for pypi.fury.io
[urllib3:urllib3.connectionpool] Starting new HTTPS connection (1): pypi.fury.io:443
[urllib3:urllib3.connectionpool] https://pypi.fury.io:443 "GET /my_source/-/VER_SOME_VERSION_HASH/my_lib-0.1.4-py3-none-any.whl HTTP/11" 403 10
>>>>>>> RES 403 >>> {'User-Agent': 'poetry/1.8.4 CPython/3.11.9 Linux/6.8.0-48-generic', 'Accept-Encoding': 'Identity', 'Accept': '*/*', 'Connection': 'keep-alive'} https://pypi.fury.io/my_source/-/VER_SOME_VERSION_HASH/my_lib-0.1.4-py3-none-any.whl#md5=40f7a6b41e90650244a8449b20b7a4db
  - Installing my_lib (0.1.4): Failed

  Stack trace:

  11  ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py:285 in _execute_operation
       283│
       284│             try:
     → 285│                 result = self._do_execute_operation(operation)
       286│             except EnvCommandError as e:
       287│                 if e.e.returncode == -2:

  10  ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py:395 in _do_execute_operation
       393│             return 0
       394│
     → 395│         result: int = getattr(self, f"_execute_{method}")(operation)
       396│
       397│         if result != 0:

   9  ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py:520 in _execute_install
       518│
       519│     def _execute_install(self, operation: Install | Update) -> int:
     → 520│         status_code = self._install(operation)
       521│
       522│         self._save_url_reference(operation)

   8  ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py:558 in _install
       556│             archive = self._download_link(operation, Link(package.source_url))
       557│         else:
     → 558│             archive = self._download(operation)
       559│
       560│         operation_message = self.get_operation_message(operation)

   7  ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py:750 in _download
       748│             self._yanked_warnings.append(message)
       749│
     → 750│         return self._download_link(operation, link)
       751│
       752│     def _download_link(self, operation: Install | Update, link: Link) -> Path:

   6  ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py:757 in _download_link
       755│         # Get original package for the link provided
       756│         download_func = functools.partial(self._download_archive, operation)
     → 757│         original_archive = self._artifact_cache.get_cached_archive_for_link(
       758│             link, strict=True, download_func=download_func
       759│         )

   5  ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/utils/cache.py:272 in get_cached_archive_for_link
       270│                     cache_dir.mkdir(parents=True, exist_ok=True)
       271│                     try:
     → 272│                         download_func(link.url, cached_archive)
       273│                     except BaseException:
       274│                         cached_archive.unlink(missing_ok=True)

   4  ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py:825 in _download_archive
       823│         dest: Path,
       824│     ) -> None:
     → 825│         downloader = Downloader(url, dest, self._authenticator)
       826│         wheel_size = downloader.total_size
       827│

   3  ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/utils/helpers.py:177 in __init__
       175│         headers = {"Accept-Encoding": "Identity"}
       176│
     → 177│         self._response = get(
       178│             url, stream=True, headers=headers, timeout=REQUESTS_TIMEOUT
       179│         )

   2  ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/utils/authenticator.py:279 in get
       277│
       278│     def get(self, url: str, **kwargs: Any) -> requests.Response:
     → 279│         return self.request("get", url, **kwargs)
       280│
       281│     def head(self, url: str, **kwargs: Any) -> requests.Response:

   1  ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/utils/authenticator.py:257 in request
       255│                         #     import ipdb
       256│                         #     ipdb.set_trace()
     → 257│                         resp.raise_for_status()
       258│                     return resp
       259│

  HTTPError

  403 Client Error: Forbidden for url: https://pypi.fury.io/my_source/-/VER_SOME_VERSION_HASH/my_lib-0.1.4-py3-none-any.whl#md5=40f7a6b41e90650244a8449b20b7a4db

  at ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/requests/models.py:1024 in raise_for_status
      1020│                 f"{self.status_code} Server Error: {reason} for url: {self.url}"
      1021│             )
      1022│
      1023│         if http_error_msg:
    → 1024│             raise HTTPError(http_error_msg, response=self)
      1025│
      1026│     def close(self):
      1027│         """Releases the connection back to the pool. Once this method has been
      1028│         called the underlying ``raw`` object must not be accessed again.

Cannot install my_lib.

  - Installing anyio (4.6.2.post1): Pending...
  - Installing anyio (4.6.2.post1): Skipped for the following reason: Already installed
  - Installing coverage (7.6.7): Pending...
  - Installing coverage (7.6.7): Skipped for the following reason: Already installed
  - Installing idna (3.10): Pending...
  - Installing idna (3.10): Skipped for the following reason: Already installed
  - Installing iniconfig (2.0.0): Pending...
  - Installing iniconfig (2.0.0): Skipped for the following reason: Already installed
  - Installing mypy (1.13.0): Pending...
  - Installing mypy (1.13.0): Skipped for the following reason: Already installed
  - Installing mypy-extensions (1.0.0): Pending...
  - Installing mypy-extensions (1.0.0): Skipped for the following reason: Already installed
  - Installing packaging (24.2): Pending...
  - Installing packaging (24.2): Skipped for the following reason: Already installed
  - Installing pluggy (1.5.0): Pending...
  - Installing pluggy (1.5.0): Skipped for the following reason: Already installed
  - Installing pydantic (1.10.19): Pending...
  - Installing pydantic (1.10.19): Skipped for the following reason: Already installed
  - Installing pyjwt (2.10.0): Pending...
  - Installing pyjwt (2.10.0): Skipped for the following reason: Already installed
  - Installing pytest (8.3.3): Pending...
  - Installing pytest (8.3.3): Skipped for the following reason: Already installed
  - Installing ruff (0.6.9): Pending...
  - Installing ruff (0.6.9): Skipped for the following reason: Already installed
  - Installing sniffio (1.3.1): Pending...
  - Installing sniffio (1.3.1): Skipped for the following reason: Already installed
  - Installing starlette (0.35.1): Pending...
  - Installing starlette (0.35.1): Skipped for the following reason: Already installed
  - Installing typing-extensions (4.12.2): Pending...
  - Installing typing-extensions (4.12.2): Skipped for the following reason: Already installed

What I tried

  1. Checked if TOKEN is valid by pip install my_lib --extra-index-url https://TOKEN@pypi.fury.io/my_source - it works

  2. Added basic auth for private source:

poetry config repositories.my_source https://${TOKEN}:@push.fury.io/my_source
poetry config http-basic.my_source $TOKEN ""
  1. Tried export POETRY_PYPI_TOKEN_FOO=$TOKEN

  2. Printed resp.status_code before 403 exception is throwing (you may find it in traceback above by >>>>>>> RES phrase) - it turned out, that when poetry discovers dependencies in repo - it connects to my pypi correctly (200 code, metadata of package obtained). But poetry fails when tries to install discovered package. In traceback above there are 3 prints with >>>>>>> RES, only the last is 403, others are 200.

  3. I fixed pyproject.toml manually to check, either add command fails or install:

# pyproject.toml
...
[tool.poetry.dependencies]
python = "^3.11"
my_lib = { version = "0.1.4", source = "my_source" }

[[tool.poetry.source]]
name = "my_source"
url = "https://pypi.fury.io/my_source/"
priority = "supplemental"
...

after that I ran poetry lock - it worked (I see all the metadata, including description, author in *.lock file about my_lib). I ran poetry install - got the same 200 > 200 > 403 as before

  1. I added trackeback.print_stack() instead of printing to check from which places code goes to this place:

image

Here it is when running poetry install after manual adding dependency and source to pyproject.toml:

(lib-server) dpw@dpw:~/ns/my_service$ poetry install -vvv
Loading configuration file /home/dpw/.config/pypoetry/config.toml
Loading configuration file /home/dpw/.config/pypoetry/auth.toml
Adding repository my_source (https://pypi.fury.io/my_source) and setting it as supplemental
Using virtualenv: /home/dpw/.pyenv/versions/3.11.9/envs/lib-server
Installing dependencies from lock file

Finding the necessary packages for the current system

Package operations: 1 install, 0 updates, 0 removals, 15 skipped

  - Installing my_lib (0.1.4): Pending...
Checking if keyring is available
[keyring:keyring.backend] Loading KWallet
[keyring:keyring.backend] Loading SecretService
[keyring:keyring.backend] Loading Windows
[keyring:keyring.backend] Loading chainer
[keyring:keyring.backend] Loading libsecret
[keyring:keyring.backend] Loading macOS
Using keyring backend 'SecretService Keyring'
Creating new session for pypi.fury.io
[urllib3:urllib3.connectionpool] Starting new HTTPS connection (1): pypi.fury.io:443
[urllib3:urllib3.connectionpool] https://pypi.fury.io:443 "GET /my_source/my_lib/ HTTP/11" 304 0
[filelock:filelock] Attempting to acquire lock 132789441235984 on /home/dpw/.cache/pypoetry/cache/repositories/my_source/_http/9/e/1/a/a/9e1aa63c395dfeb329a3132377c50d4750b7a3001fb8fbe3407dc940.lock
[filelock:filelock] Lock 132789441235984 acquired on /home/dpw/.cache/pypoetry/cache/repositories/my_source/_http/9/e/1/a/a/9e1aa63c395dfeb329a3132377c50d4750b7a3001fb8fbe3407dc940.lock
[filelock:filelock] Attempting to release lock 132789441235984 on /home/dpw/.cache/pypoetry/cache/repositories/my_source/_http/9/e/1/a/a/9e1aa63c395dfeb329a3132377c50d4750b7a3001fb8fbe3407dc940.lock
[filelock:filelock] Lock 132789441235984 released on /home/dpw/.cache/pypoetry/cache/repositories/my_source/_http/9/e/1/a/a/9e1aa63c395dfeb329a3132377c50d4750b7a3001fb8fbe3407dc940.lock
Source (my_source): Downloading: https://pypi.fury.io/my_source/-/VER_SOME_VERSION_HASH/my_lib-0.1.4-py3-none-any.whl#md5=40f7a6b41e90650244a8449b20b7a4db
[urllib3:urllib3.connectionpool] https://pypi.fury.io:443 "GET /my_source/-/VER_SOME_VERSION_HASH/my_lib-0.1.4-py3-none-any.whl HTTP/11" 200 7867
TRACE
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  File "/home/dpw/.pyenv/versions/3.11.9/lib/python3.11/threading.py", line 1002, in _bootstrap
    self._bootstrap_inner()
  File "/home/dpw/.pyenv/versions/3.11.9/lib/python3.11/threading.py", line 1045, in _bootstrap_inner
    self.run()
  File "/home/dpw/.pyenv/versions/3.11.9/lib/python3.11/threading.py", line 982, in run
    self._target(*self._args, **self._kwargs)
  File "/home/dpw/.pyenv/versions/3.11.9/lib/python3.11/concurrent/futures/thread.py", line 83, in _worker
    work_item.run()
  File "/home/dpw/.pyenv/versions/3.11.9/lib/python3.11/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py", line 285, in _execute_operation
    result = self._do_execute_operation(operation)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py", line 395, in _do_execute_operation
    result: int = getattr(self, f"_execute_{method}")(operation)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py", line 520, in _execute_install
    status_code = self._install(operation)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py", line 558, in _install
    archive = self._download(operation)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py", line 736, in _download
    link = self._chooser.choose_for(operation.package)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/chooser.py", line 48, in choose_for
    for link in self._get_links(package):
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/chooser.py", line 111, in _get_links
    link_hash = repository.calculate_sha256(link)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/repositories/http_repository.py", line 374, in calculate_sha256
    with self._cached_or_downloaded_file(link) as filepath:
  File "/home/dpw/.pyenv/versions/3.11.9/lib/python3.11/contextlib.py", line 137, in __enter__
    return next(self.gen)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/repositories/http_repository.py", line 108, in _cached_or_downloaded_file
    self._download(
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/repositories/http_repository.py", line 97, in _download
    return download_file(
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/utils/helpers.py", line 139, in download_file
    downloader = Downloader(url, dest, session)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/utils/helpers.py", line 177, in __init__
    self._response = get(
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/utils/authenticator.py", line 279, in get
    return self.request("get", url, **kwargs)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/utils/authenticator.py", line 248, in request
    traceback.print_stack()
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
>>>>>>> RES 200 >>> {'User-Agent': 'poetry/1.8.4 CPython/3.11.9 Linux/6.8.0-48-generic', 'Accept-Encoding': 'Identity', 'Accept': '*/*', 'Connection': 'keep-alive', 'Authorization': 'Basic POETRY_GENERATED_AUTH_TOKEN'} https://pypi.fury.io/my_source/-/VER_SOME_VERSION_HASH/my_lib-0.1.4-py3-none-any.whl#md5=40f7a6b41e90650244a8449b20b7a4db
[filelock:filelock] Attempting to acquire lock 132789430130640 on /home/dpw/.cache/pypoetry/cache/repositories/my_source/_http/f/a/a/1/9/faa19d22d4591021c8183bf5044fc7c01b0bc268e35440781473a5d4.lock
[filelock:filelock] Lock 132789430130640 acquired on /home/dpw/.cache/pypoetry/cache/repositories/my_source/_http/f/a/a/1/9/faa19d22d4591021c8183bf5044fc7c01b0bc268e35440781473a5d4.lock
[filelock:filelock] Attempting to release lock 132789430130640 on /home/dpw/.cache/pypoetry/cache/repositories/my_source/_http/f/a/a/1/9/faa19d22d4591021c8183bf5044fc7c01b0bc268e35440781473a5d4.lock
[filelock:filelock] Lock 132789430130640 released on /home/dpw/.cache/pypoetry/cache/repositories/my_source/_http/f/a/a/1/9/faa19d22d4591021c8183bf5044fc7c01b0bc268e35440781473a5d4.lock
There are no known hash types for my_lib-0.1.4-py3-none-any.whl that are prioritised (known hash types: {'md5'})
Source (my_source): Downloading: https://pypi.fury.io/my_source/-/VER_SOME_VERSION_HASH/my_lib-0.1.4.tar.gz#md5=4c7a0c9c48a3d68984d1bec05639dc50
[urllib3:urllib3.connectionpool] https://pypi.fury.io:443 "GET /my_source/-/VER_SOME_VERSION_HASH/my_lib-0.1.4.tar.gz HTTP/11" 200 7124
TRACE
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  File "/home/dpw/.pyenv/versions/3.11.9/lib/python3.11/threading.py", line 1002, in _bootstrap
    self._bootstrap_inner()
  File "/home/dpw/.pyenv/versions/3.11.9/lib/python3.11/threading.py", line 1045, in _bootstrap_inner
    self.run()
  File "/home/dpw/.pyenv/versions/3.11.9/lib/python3.11/threading.py", line 982, in run
    self._target(*self._args, **self._kwargs)
  File "/home/dpw/.pyenv/versions/3.11.9/lib/python3.11/concurrent/futures/thread.py", line 83, in _worker
    work_item.run()
  File "/home/dpw/.pyenv/versions/3.11.9/lib/python3.11/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py", line 285, in _execute_operation
    result = self._do_execute_operation(operation)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py", line 395, in _do_execute_operation
    result: int = getattr(self, f"_execute_{method}")(operation)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py", line 520, in _execute_install
    status_code = self._install(operation)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py", line 558, in _install
    archive = self._download(operation)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py", line 736, in _download
    link = self._chooser.choose_for(operation.package)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/chooser.py", line 48, in choose_for
    for link in self._get_links(package):
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/chooser.py", line 111, in _get_links
    link_hash = repository.calculate_sha256(link)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/repositories/http_repository.py", line 374, in calculate_sha256
    with self._cached_or_downloaded_file(link) as filepath:
  File "/home/dpw/.pyenv/versions/3.11.9/lib/python3.11/contextlib.py", line 137, in __enter__
    return next(self.gen)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/repositories/http_repository.py", line 108, in _cached_or_downloaded_file
    self._download(
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/repositories/http_repository.py", line 97, in _download
    return download_file(
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/utils/helpers.py", line 139, in download_file
    downloader = Downloader(url, dest, session)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/utils/helpers.py", line 177, in __init__
    self._response = get(
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/utils/authenticator.py", line 279, in get
    return self.request("get", url, **kwargs)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/utils/authenticator.py", line 248, in request
    traceback.print_stack()
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
>>>>>>> RES 200 >>> {'User-Agent': 'poetry/1.8.4 CPython/3.11.9 Linux/6.8.0-48-generic', 'Accept-Encoding': 'Identity', 'Accept': '*/*', 'Connection': 'keep-alive', 'Authorization': 'Basic POETRY_GENERATED_AUTH_TOKEN'} https://pypi.fury.io/my_source/-/VER_SOME_VERSION_HASH/my_lib-0.1.4.tar.gz#md5=4c7a0c9c48a3d68984d1bec05639dc50
[filelock:filelock] Attempting to acquire lock 132789430132624 on /home/dpw/.cache/pypoetry/cache/repositories/my_source/_http/d/f/a/6/d/dfa6d53cf2df66a53d779e8dfa4a21c6d51014acb69c81fb227a8204.lock
[filelock:filelock] Lock 132789430132624 acquired on /home/dpw/.cache/pypoetry/cache/repositories/my_source/_http/d/f/a/6/d/dfa6d53cf2df66a53d779e8dfa4a21c6d51014acb69c81fb227a8204.lock
[filelock:filelock] Attempting to release lock 132789430132624 on /home/dpw/.cache/pypoetry/cache/repositories/my_source/_http/d/f/a/6/d/dfa6d53cf2df66a53d779e8dfa4a21c6d51014acb69c81fb227a8204.lock
[filelock:filelock] Lock 132789430132624 released on /home/dpw/.cache/pypoetry/cache/repositories/my_source/_http/d/f/a/6/d/dfa6d53cf2df66a53d779e8dfa4a21c6d51014acb69c81fb227a8204.lock
There are no known hash types for my_lib-0.1.4.tar.gz that are prioritised (known hash types: {'md5'})
There are no known hash types for my_lib-0.1.4-py3-none-any.whl that are prioritised (known hash types: {'md5'})
Checking if keyring is available
Using keyring backend 'SecretService Keyring'
Creating new session for pypi.fury.io
[urllib3:urllib3.connectionpool] Starting new HTTPS connection (1): pypi.fury.io:443
[urllib3:urllib3.connectionpool] https://pypi.fury.io:443 "GET /my_source/-/VER_SOME_VERSION_HASH/my_lib-0.1.4-py3-none-any.whl HTTP/11" 403 10
TRACE
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  File "/home/dpw/.pyenv/versions/3.11.9/lib/python3.11/threading.py", line 1002, in _bootstrap
    self._bootstrap_inner()
  File "/home/dpw/.pyenv/versions/3.11.9/lib/python3.11/threading.py", line 1045, in _bootstrap_inner
    self.run()
  File "/home/dpw/.pyenv/versions/3.11.9/lib/python3.11/threading.py", line 982, in run
    self._target(*self._args, **self._kwargs)
  File "/home/dpw/.pyenv/versions/3.11.9/lib/python3.11/concurrent/futures/thread.py", line 83, in _worker
    work_item.run()
  File "/home/dpw/.pyenv/versions/3.11.9/lib/python3.11/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py", line 285, in _execute_operation
    result = self._do_execute_operation(operation)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py", line 395, in _do_execute_operation
    result: int = getattr(self, f"_execute_{method}")(operation)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py", line 520, in _execute_install
    status_code = self._install(operation)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py", line 558, in _install
    archive = self._download(operation)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py", line 750, in _download
    return self._download_link(operation, link)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py", line 757, in _download_link
    original_archive = self._artifact_cache.get_cached_archive_for_link(
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/utils/cache.py", line 272, in get_cached_archive_for_link
    download_func(link.url, cached_archive)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py", line 825, in _download_archive
    downloader = Downloader(url, dest, self._authenticator)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/utils/helpers.py", line 177, in __init__
    self._response = get(
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/utils/authenticator.py", line 279, in get
    return self.request("get", url, **kwargs)
  File "/home/dpw/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/utils/authenticator.py", line 248, in request
    traceback.print_stack()
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
>>>>>>> RES 403 >>> {'User-Agent': 'poetry/1.8.4 CPython/3.11.9 Linux/6.8.0-48-generic', 'Accept-Encoding': 'Identity', 'Accept': '*/*', 'Connection': 'keep-alive'} https://pypi.fury.io/my_source/-/VER_SOME_VERSION_HASH/my_lib-0.1.4-py3-none-any.whl#md5=40f7a6b41e90650244a8449b20b7a4db
  - Installing my_lib (0.1.4): Failed

  Stack trace:

  11  ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py:285 in _execute_operation
       283│ 
       284│             try:
     → 285│                 result = self._do_execute_operation(operation)
       286│             except EnvCommandError as e:
       287│                 if e.e.returncode == -2:

  10  ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py:395 in _do_execute_operation
       393│             return 0
       394│ 
     → 395│         result: int = getattr(self, f"_execute_{method}")(operation)
       396│ 
       397│         if result != 0:

   9  ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py:520 in _execute_install
       518│ 
       519│     def _execute_install(self, operation: Install | Update) -> int:
     → 520│         status_code = self._install(operation)
       521│ 
       522│         self._save_url_reference(operation)

   8  ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py:558 in _install
       556│             archive = self._download_link(operation, Link(package.source_url))
       557│         else:
     → 558│             archive = self._download(operation)
       559│ 
       560│         operation_message = self.get_operation_message(operation)

   7  ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py:750 in _download
       748│             self._yanked_warnings.append(message)
       749│ 
     → 750│         return self._download_link(operation, link)
       751│ 
       752│     def _download_link(self, operation: Install | Update, link: Link) -> Path:

   6  ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py:757 in _download_link
       755│         # Get original package for the link provided
       756│         download_func = functools.partial(self._download_archive, operation)
     → 757│         original_archive = self._artifact_cache.get_cached_archive_for_link(
       758│             link, strict=True, download_func=download_func
       759│         )

   5  ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/utils/cache.py:272 in get_cached_archive_for_link
       270│                     cache_dir.mkdir(parents=True, exist_ok=True)
       271│                     try:
     → 272│                         download_func(link.url, cached_archive)
       273│                     except BaseException:
       274│                         cached_archive.unlink(missing_ok=True)

   4  ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/installation/executor.py:825 in _download_archive
       823│         dest: Path,
       824│     ) -> None:
     → 825│         downloader = Downloader(url, dest, self._authenticator)
       826│         wheel_size = downloader.total_size
       827│ 

   3  ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/utils/helpers.py:177 in __init__
       175│         headers = {"Accept-Encoding": "Identity"}
       176│ 
     → 177│         self._response = get(
       178│             url, stream=True, headers=headers, timeout=REQUESTS_TIMEOUT
       179│         )

   2  ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/utils/authenticator.py:279 in get
       277│ 
       278│     def get(self, url: str, **kwargs: Any) -> requests.Response:
     → 279│         return self.request("get", url, **kwargs)
       280│ 
       281│     def head(self, url: str, **kwargs: Any) -> requests.Response:

   1  ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/poetry/utils/authenticator.py:257 in request
       255│                         #     import ipdb
       256│                         #     ipdb.set_trace()
     → 257│                         resp.raise_for_status()
       258│                     return resp
       259│ 

  HTTPError

  403 Client Error: Forbidden for url: https://pypi.fury.io/my_source/-/VER_SOME_VERSION_HASH/my_lib-0.1.4-py3-none-any.whl#md5=40f7a6b41e90650244a8449b20b7a4db

  at ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/requests/models.py:1024 in raise_for_status
      1020│                 f"{self.status_code} Server Error: {reason} for url: {self.url}"
      1021│             )
      1022│ 
      1023│         if http_error_msg:
    → 1024│             raise HTTPError(http_error_msg, response=self)
      1025│ 
      1026│     def close(self):
      1027│         """Releases the connection back to the pool. Once this method has been
      1028│         called the underlying ``raw`` object must not be accessed again.

Cannot install my_lib.
...

As you may see, poetry fails with 403 when trying access already downloaded package taking it in get_cached_archive_for_link.

  1. I went further, printing headers (here) to request - it turned out that 3rd time poetry doesn't attach Authorization token with gives 403:
# code on utils/authenticator.py:245
print(">>>>>>> RES", resp.status_code, ">>>>>>>>\nHeaders:", resp.request.headers, "\nURL:", resp.request.url, "\nUsed authenticator:", self)

# Printed for command `poetry install`

Installing dependencies from lock file
Package operations: 1 install, 0 updates, 0 removals

  - Installing my_lib (0.1.4): Pending...
>>>>>>> RES 200 >>>>>>>>
Headers: {'User-Agent': 'poetry/1.8.4 CPython/3.11.9 Linux/6.8.0-48-generic', 'Accept-Encoding': 'Identity', 'Accept': '*/*', 'Connection': 'keep-alive', 'Authorization': 'Basic POETRY_GENERATED_AUTH_TOKEN'} 
URL: https://pypi.fury.io/my_source/-/VER_SOME_VERSION_HASH/my_lib-0.1.4-py3-none-any.whl#md5=40f7a6b41e90650244a8449b20b7a4db 
Used authenticator: <poetry.utils.authenticator.Authenticator object at 0x7bf95f587550>

>>>>>>> RES 200 >>>>>>>>
Headers: {'User-Agent': 'poetry/1.8.4 CPython/3.11.9 Linux/6.8.0-48-generic', 'Accept-Encoding': 'Identity', 'Accept': '*/*', 'Connection': 'keep-alive', 'Authorization': 'Basic POETRY_GENERATED_AUTH_TOKEN'} 
URL: https://pypi.fury.io/my_source/-/VER_SOME_VERSION_HASH/my_lib-0.1.4.tar.gz#md5=4c7a0c9c48a3d68984d1bec05639dc50
Used authenticator: <poetry.utils.authenticator.Authenticator object at 0x7bf95f587550>

>>>>>>> RES 403 >>>>>>>>
Headers: {'User-Agent': 'poetry/1.8.4 CPython/3.11.9 Linux/6.8.0-48-generic', 'Accept-Encoding': 'Identity', 'Accept': '*/*', 'Connection': 'keep-alive'} 
URL: https://pypi.fury.io/my_source/-/VER_SOME_VERSION_HASH/my_lib-0.1.4-py3-none-any.whl#md5=40f7a6b41e90650244a8449b20b7a4db
Used authenticator: <poetry.utils.authenticator.Authenticator object at 0x7bf95f53fa50>
  - Installing my_lib (0.1.4): Failed

  HTTPError

  403 Client Error: Forbidden for url: https://pypi.fury.io/my_source/-/VER_SOME_VERSION_HASH/my_lib-0.1.4-py3-none-any.whl#md5=40f7a6b41e90650244a8449b20b7a4db

  at ~/.pyenv/versions/3.11.9/envs/lib-server/lib/python3.11/site-packages/requests/models.py:1024 in raise_for_status
      1020│                 f"{self.status_code} Server Error: {reason} for url: {self.url}"
      1021│             )
      1022│ 
      1023│         if http_error_msg:
    → 1024│             raise HTTPError(http_error_msg, response=self)
      1025│ 
      1026│     def close(self):
      1027│         """Releases the connection back to the pool. Once this method has been
      1028│         called the underlying ``raw`` object must not be accessed again.

Cannot install my_lib.

What is interesting here - Authenticator object is the same 1st and 2nd time, but another at 3rd call when package is already cached.

  1. I decided maybe it's some trouble with parallel run by default and turned off installer.parallel, set installer.max-workers = 1, this is my final config:
(lib-server) dpw@dpw:~/ns/my_service poetry config --list
cache-dir = "/home/dpw/.cache/pypoetry"
experimental.system-git-client = false
installer.max-workers = 1
installer.modern-installation = true
installer.no-binary = null
installer.parallel = false
keyring.enabled = true
repositories.my_source.url = "https://TOKEN:@push.fury.io/my_source"
solver.lazy-wheel = true
virtualenvs.create = false
virtualenvs.in-project = null
virtualenvs.options.always-copy = false
virtualenvs.options.no-pip = false
virtualenvs.options.no-setuptools = false
virtualenvs.options.system-site-packages = false
virtualenvs.path = "{cache-dir}/virtualenvs"  # /home/dpw/.cache/pypoetry/virtualenvs
virtualenvs.prefer-active-python = false
virtualenvs.prompt = "{project_name}-py{python_version}"
warnings.export = true

It didn't help - Authenticator object on 3rd call differs from 1st and 2nd calls still.

  1. If I took Authorization header which poetry generated (from my prints). Tried to download package my_lib directly from browser with that auth header - it downloaded well.

So, I consider it as problem on poetry side. Appreciate any help and workarounds!

What issues I checked and tried workarounds (spoiler - nothing helped)

  1. setting up gemfury is not obvious #910 (comment)
  2. Creating and publishing a private repo with token #919 (comment)
  3. setting up gemfury is not obvious #910
  4. Auth failure when installing from multiple private repos #3291
  5. [[tool.poetry.source]] setting is ignored #3474

@abn
Copy link
Member

abn commented Nov 20, 2024

@DariaPlotnikova think your issue was resolved in #9850

As a workaround (for Gemfury users) try:

poetry config http-basic.my_source $TOKEN $TOKEN

See exception documented at https://gemfury.com/help/errors/repo-url-password/.

@abn
Copy link
Member

abn commented Nov 20, 2024

@DariaPlotnikova thank you for the effort to debug the issue and the information provided. Hopefully the fix and/or workaround will solve your immediate issue.

@abn abn added area/auth Related to the authenticator and keyring area/sources Releated to package sources/indexes/repositories and removed status/triage This issue needs to be triaged labels Nov 20, 2024
@DariaPlotnikova
Copy link

DariaPlotnikova commented Nov 20, 2024

@abn Thanks for fast reaction. Hope we could fix is as fast as possible.
I tried all the combination with configs http-basic.my_source + pypi-token.my_source:

  • http-basic.my_source $TOKEN "" only, without pypi-token.my_source (tried $TOKEN "", $TOKEN NOPASS, __token__ $TOKEN, $TOKEN $TOKEN, my_source $TOKEN)
  • http-basic.my_source $TOKEN "" with pypi-token.my_source.username and pypi-token.my_source.password configured (again tried different variants as in point 1)
  • only pypi-token.my_source.username without http-basic.

(Also I deleted and fully recreated my env, cleared poetry cache)

I continued debugging. What I found is that "magic" happens in Authenticator._get_credentials_for_url():

  1. On first call url param is just http://pypi.fury.io/my_source, there are such creds configured, they are initiated and put to Authenticator()._credentials instance cache.
  2. On 2nd call url is package's certain version wheel url, there are no such creds in cache in Authenticator()._credentials, and the cache contains pypi, and my private repo cache (from 1st call) already
  3. On 3rd call url is tar.gz of certain package's version. And what is strange - at this moment, Authenticator()._credentials is empty, despite it was filled with pypi and my private repo on the previous call.

This leads to empty repository here on 3rd (tar.gz) call of Authenticator().request which returns empty credentials for the repos => no auth for API call.

Also I printed thread and process IDs in Authenticator().request(): on the 1st and 2nd calls it is MainProcess + MainThread, on 3rd call it is MainProcess + ThreadPoolExecutor. This also was confirmed in my original post, where I printed Authenticator instance ID - it was different for 3rd Authenticator.request() call comsparing to 1st and 2nd.

May there be some threading problem?

@abn
Copy link
Member

abn commented Nov 20, 2024

@DariaPlotnikova please see my comment above at #4181 (comment) for the workaround.

The issue is already fixed. And the workaround above should work for your case. 😄

@DariaPlotnikova
Copy link

DariaPlotnikova commented Nov 21, 2024

@abn thanks a lot! I tried your advice again after fully reinstalling poetry in system globally.
I found out in gemfury docs you provided that repo url should be on domain repo.fury.io, not pypi.fury.io. Now everything works:

  • changed repo URL to https://repo.fury.io/my_source/ as supplemental source
  • set up poetry config http-basic.my_source $TOKEN $TOKEN

@DariaPlotnikova
Copy link

@abn could you please tell, which version will your fix go to? Locally everything is ok with workaround, but in CI - no (probably because of no keyrings in CI). My case is that I have 2 librarier, lib_a, lib_b, both are in private repo. And lib_b requires lib_a.

Fast fix for CI: pre-install with pip your local package:

# .gitlab-ci.yaml
test lib:
  ...
  script:
    - pip install lib_a==0.0.1 --extra-index-url https://$TOKEN@repo.fury.io/my_source
    - poetry install --no-root --all-extras

@abn
Copy link
Member

abn commented Nov 22, 2024

@DariaPlotnikova with the poetry config http-basic.my_source $TOKEN $TOKEN workaround you do not need a new release for this, you can drop pip install assuming both packages are in the same source and you have added lib_a as a dependency with the source specified (poetry add --source=my_source lib_a), it should just work.

Copy link

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Dec 23, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area/auth Related to the authenticator and keyring area/sources Releated to package sources/indexes/repositories kind/bug Something isn't working as expected
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants