Skip to content

feat: allow caller data in request user agents - #11047

Open
GruffElixir wants to merge 3 commits into
python-poetry:mainfrom
GruffElixir:fix/11012-user-agent-data
Open

feat: allow caller data in request user agents#11047
GruffElixir wants to merge 3 commits into
python-poetry:mainfrom
GruffElixir:fix/11012-user-agent-data

Conversation

@GruffElixir

Copy link
Copy Markdown

Resolves: #11012

Summary

  • Add POETRY_USER_AGENT_USER_DATA to append caller context to Poetry's User-Agent.
  • Apply the same User-Agent construction to repository sessions and package uploads.
  • Document the environment variable and cover both request paths with regression tests.

Validation

  • python -m pytest -o addopts='' -q tests/utils/test_authenticator.py tests/publishing/test_uploader.py

  • python -m ruff check src/poetry/utils/user_agent.py src/poetry/utils/authenticator.py src/poetry/publishing/uploader.py tests/utils/test_authenticator.py tests/publishing/test_uploader.py

  • python -m ruff format --check src/poetry/utils/user_agent.py src/poetry/utils/authenticator.py src/poetry/publishing/uploader.py tests/utils/test_authenticator.py tests/publishing/test_uploader.py

  • git diff --check

  • Added tests for changed code.

  • Updated documentation for changed code.

Copilot AI lite review requested due to automatic review settings September 6, 2026 20:11

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="src/poetry/utils/user_agent.py" line_range="12-15" />
<code_context>
+    extras: list[tuple[str, str]] = []
+    user_data = os.environ.get("POETRY_USER_AGENT_USER_DATA")
+    if user_data is not None:
+        extras.append(("user_data", user_data))
+
+    return requests_user_agent("poetry", __version__, extras=extras)
</code_context>
<issue_to_address>
**issue (bug_risk):** `requests_toolbelt.user_agent` expects `extras` to contain strings such as `"user_data/build/42"`, but this code appends a tuple. When `POETRY_USER_AGENT_USER_DATA` is set, User-Agent construction raises `TypeError` instead of returning a header, breaking repository requests and uploads.

**Triggers:** When `POETRY_USER_AGENT_USER_DATA` is set.

**Suggested fix:** Append `f"user_data/{user_data}"` as a string rather than the tuple `("user_data", user_data)`.

```suggestion
    extras: list[str] = []
    user_data = os.environ.get("POETRY_USER_AGENT_USER_DATA")
    if user_data is not None:
        extras.append(f"user_data/{user_data}")
```
</issue_to_address>

Sourcery assessment

Needs a human reviewer. 1 finding to address first, and if the configured value is sensitive or malformed, Poetry will send it to package repositories in download and upload request headers, and those disclosures cannot be undone by reverting the change. The behavior is opt-in and future exposure stops on revert, but already transmitted caller data cannot be recalled.

Blocking findings: src/poetry/utils/user_agent.py:15


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment on lines +12 to +15
extras: list[tuple[str, str]] = []
user_data = os.environ.get("POETRY_USER_AGENT_USER_DATA")
if user_data is not None:
extras.append(("user_data", user_data))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): requests_toolbelt.user_agent expects extras to contain strings such as "user_data/build/42", but this code appends a tuple. When POETRY_USER_AGENT_USER_DATA is set, User-Agent construction raises TypeError instead of returning a header, breaking repository requests and uploads.

Triggers: When POETRY_USER_AGENT_USER_DATA is set.

Suggested fix: Append f"user_data/{user_data}" as a string rather than the tuple ("user_data", user_data).

Suggested change
extras: list[tuple[str, str]] = []
user_data = os.environ.get("POETRY_USER_AGENT_USER_DATA")
if user_data is not None:
extras.append(("user_data", user_data))
extras: list[str] = []
user_data = os.environ.get("POETRY_USER_AGENT_USER_DATA")
if user_data is not None:
extras.append(f"user_data/{user_data}")

@GruffElixir

Copy link
Copy Markdown
Author

The existing tuple is intentional: requests-toolbelt 1.0.0 documents extras as two-item tuples and formats ("user_data", "build/42") as user_data/build/42. Both affected Poetry tests pass with POETRY_USER_AGENT_USER_DATA=build/42; changing this to a string would violate that API. No code change is needed for this finding.

@GruffElixir
GruffElixir force-pushed the fix/11012-user-agent-data branch from 44942e4 to 0aa0a3f Compare September 7, 2026 21:15
@GruffElixir
GruffElixir force-pushed the fix/11012-user-agent-data branch from 0aa0a3f to 4d59b92 Compare September 8, 2026 11:16
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

Successfully merging this pull request may close these issues.

Allow appending caller-supplied data to the User-Agent (pip's PIP_USER_AGENT_USER_DATA equivalent)

2 participants