From f787788a65cf7a8af8b7ef9dc13c0681d94fff5f Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 16 May 2021 21:19:15 -0400 Subject: [PATCH 1/4] Include rustc version in the user agent, if rustc is available Rust is becoming more popular for writing Python extension modules in, this information would be valuable for package maintainers to assess the ecosystem, in the same way glibc or openssl version is. --- src/pip/_internal/network/session.py | 17 +++++++++++++++++ tests/unit/test_req_file.py | 6 ++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/pip/_internal/network/session.py b/src/pip/_internal/network/session.py index 4af800f12fe..78536f1c4b5 100644 --- a/src/pip/_internal/network/session.py +++ b/src/pip/_internal/network/session.py @@ -19,6 +19,8 @@ import mimetypes import os import platform +import shutil +import subprocess import sys import urllib.parse import warnings @@ -163,6 +165,21 @@ def user_agent(): if setuptools_dist is not None: data["setuptools_version"] = str(setuptools_dist.version) + if shutil.which("rustc") is not None: + # If for any reason `rustc --version` fails, silently ignore it + try: + rustc_output = subprocess.check_output( + ["rustc", "--version"], stderr=subprocess.STDOUT + ) + except Exception: + pass + else: + if rustc_output.startswith(b"rustc "): + # The format of `rustc --version` is: + # `b'rustc 1.52.1 (9bc8c42bb 2021-05-09)\n'` + # We extract just the middle (1.52.1) part + data["rustc_version"] = rustc_output.split(b" ")[1].decode() + # Use None rather than False so as not to give the impression that # pip knows it is not being run under CI. Rather, it is a null or # inconclusive result. Also, we include some value rather than no diff --git a/tests/unit/test_req_file.py b/tests/unit/test_req_file.py index 3c534c9ee01..cecab63babc 100644 --- a/tests/unit/test_req_file.py +++ b/tests/unit/test_req_file.py @@ -598,13 +598,14 @@ def make_var(name): with open(tmpdir.joinpath('req1.txt'), 'w') as fp: fp.write(template.format(*map(make_var, env_vars))) + session = PipSession() with patch('pip._internal.req.req_file.os.getenv') as getenv: getenv.side_effect = lambda n: env_vars[n] reqs = list(parse_reqfile( tmpdir.joinpath('req1.txt'), finder=finder, - session=PipSession() + session=session )) assert len(reqs) == 1, \ @@ -623,13 +624,14 @@ def test_expand_missing_env_variables(self, tmpdir, finder): with open(tmpdir.joinpath('req1.txt'), 'w') as fp: fp.write(req_url) + session = PipSession() with patch('pip._internal.req.req_file.os.getenv') as getenv: getenv.return_value = '' reqs = list(parse_reqfile( tmpdir.joinpath('req1.txt'), finder=finder, - session=PipSession() + session=session )) assert len(reqs) == 1, \ From 722ba2dd1634b72ec72c03cad507a12455f3e74c Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 17 May 2021 08:01:04 -0400 Subject: [PATCH 2/4] Added a new fragment --- news/9987.feature.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 news/9987.feature.rst diff --git a/news/9987.feature.rst b/news/9987.feature.rst new file mode 100644 index 00000000000..0cf4516381d --- /dev/null +++ b/news/9987.feature.rst @@ -0,0 +1 @@ +Include ``rustc`` version in pip's ``User-Agent``, when the system has ``rustc``. From 248b6785a45a584ca66be2f2fc38721fe5fb8c72 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 17 May 2021 17:15:27 -0400 Subject: [PATCH 3/4] Added comments --- tests/unit/test_req_file.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/unit/test_req_file.py b/tests/unit/test_req_file.py index cecab63babc..be1e5815f2b 100644 --- a/tests/unit/test_req_file.py +++ b/tests/unit/test_req_file.py @@ -598,6 +598,8 @@ def make_var(name): with open(tmpdir.joinpath('req1.txt'), 'w') as fp: fp.write(template.format(*map(make_var, env_vars))) + # Construct the session outside the monkey-patch, since it access the + # env session = PipSession() with patch('pip._internal.req.req_file.os.getenv') as getenv: getenv.side_effect = lambda n: env_vars[n] @@ -624,6 +626,8 @@ def test_expand_missing_env_variables(self, tmpdir, finder): with open(tmpdir.joinpath('req1.txt'), 'w') as fp: fp.write(req_url) + # Construct the session outside the monkey-patch, since it access the + # env session = PipSession() with patch('pip._internal.req.req_file.os.getenv') as getenv: getenv.return_value = '' From 9ab448de634aca8e2bf4ef3f64bc2dbb4641d1cc Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 20 May 2021 19:24:54 -0400 Subject: [PATCH 4/4] Added a timeout to invoking rustc --- src/pip/_internal/network/session.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pip/_internal/network/session.py b/src/pip/_internal/network/session.py index 78536f1c4b5..dca26374458 100644 --- a/src/pip/_internal/network/session.py +++ b/src/pip/_internal/network/session.py @@ -169,7 +169,7 @@ def user_agent(): # If for any reason `rustc --version` fails, silently ignore it try: rustc_output = subprocess.check_output( - ["rustc", "--version"], stderr=subprocess.STDOUT + ["rustc", "--version"], stderr=subprocess.STDOUT, timeout=.5 ) except Exception: pass