Skip to content

Commit ec859fb

Browse files
committed
Set user-agent & retries for OIDC requests
1 parent 9c4506c commit ec859fb

File tree

3 files changed

+30
-33
lines changed

3 files changed

+30
-33
lines changed

twine/auth.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from typing import TYPE_CHECKING, Callable, Optional, Type, cast
66
from urllib.parse import urlparse
77

8-
import requests
98
from id import AmbientCredentialError # type: ignore
109
from id import detect_credential
1110

@@ -77,7 +76,7 @@ def make_trusted_publishing_token(self) -> Optional[str]:
7776
# Trusted publishing (OpenID Connect): get one token from the CI
7877
# system, and exchange that for a PyPI token.
7978
repository_domain = cast(str, urlparse(self.system).netloc)
80-
session = requests.Session() # TODO: user agent & retries
79+
session = utils.make_requests_session()
8180

8281
# Indices are expected to support `https://{domain}/_/oidc/audience`,
8382
# which tells OIDC exchange clients which audience to use.

twine/repository.py

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,15 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414
import logging
15-
from typing import Any, Dict, List, Optional, Set, Tuple, cast
15+
from typing import Any, Dict, List, Optional, Set, Tuple
1616

1717
import requests
1818
import requests_toolbelt
1919
import rich.progress
20-
import urllib3
21-
from requests import adapters
22-
from requests_toolbelt.utils import user_agent
2320
from rich import print
2421

25-
import twine
2622
from twine import package as package_file
23+
from twine.utils import make_requests_session
2724

2825
KEYWORDS_TO_NOT_FLATTEN = {"gpg_signature", "attestations", "content"}
2926

@@ -47,7 +44,7 @@ def __init__(
4744
) -> None:
4845
self.url = repository_url
4946

50-
self.session = requests.session()
47+
self.session = make_requests_session()
5148
# requests.Session.auth should be Union[None, Tuple[str, str], ...]
5249
# But username or password could be None
5350
# See TODO for utils.RepositoryConfig
@@ -57,35 +54,10 @@ def __init__(
5754
logger.info(f"username: {username if username else '<empty>'}")
5855
logger.info(f"password: <{'hidden' if password else 'empty'}>")
5956

60-
self.session.headers["User-Agent"] = self._make_user_agent_string()
61-
for scheme in ("http://", "https://"):
62-
self.session.mount(scheme, self._make_adapter_with_retries())
63-
6457
# Working around https://github.com/python/typing/issues/182
6558
self._releases_json_data: Dict[str, Dict[str, Any]] = {}
6659
self.disable_progress_bar = disable_progress_bar
6760

68-
@staticmethod
69-
def _make_adapter_with_retries() -> adapters.HTTPAdapter:
70-
retry = urllib3.Retry(
71-
allowed_methods=["GET"],
72-
connect=5,
73-
total=10,
74-
status_forcelist=[500, 501, 502, 503],
75-
)
76-
77-
return adapters.HTTPAdapter(max_retries=retry)
78-
79-
@staticmethod
80-
def _make_user_agent_string() -> str:
81-
user_agent_string = (
82-
user_agent.UserAgentBuilder("twine", twine.__version__)
83-
.include_implementation()
84-
.build()
85-
)
86-
87-
return cast(str, user_agent_string)
88-
8961
def close(self) -> None:
9062
self.session.close()
9163

twine/utils.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@
2525

2626
import requests
2727
import rfc3986
28+
import urllib3
29+
from requests.adapters import HTTPAdapter
30+
from requests_toolbelt.utils import user_agent
2831

32+
import twine
2933
from twine import exceptions
3034

3135
# Shim for input to allow testing.
@@ -304,6 +308,28 @@ def get_userpass_value(
304308
get_clientcert = functools.partial(get_userpass_value, key="client_cert")
305309

306310

311+
def make_requests_session() -> requests.Session:
312+
"""Prepare a requests Session with retries & twine's user-agent string."""
313+
s = requests.Session()
314+
315+
retry = urllib3.Retry(
316+
allowed_methods=["GET"],
317+
connect=5,
318+
total=10,
319+
status_forcelist=[500, 501, 502, 503],
320+
)
321+
322+
for scheme in ("http://", "https://"):
323+
s.mount(scheme, HTTPAdapter(max_retries=retry))
324+
325+
s.headers["User-Agent"] = (
326+
user_agent.UserAgentBuilder("twine", twine.__version__)
327+
.include_implementation()
328+
.build()
329+
)
330+
return s
331+
332+
307333
class EnvironmentDefault(argparse.Action):
308334
"""Get values from environment variable."""
309335

0 commit comments

Comments
 (0)