1
1
Fork 0
mirror of https://github.com/pypa/pip synced 2023-12-13 21:30:23 +01:00

Remove uses of utcnow in non-vendored code (#12006)

* Remove reference to utcnow

This cleans up some of the datetime handling in the self check.

Note that this changes the format of the state file, since the datetime
now uses ``.isoformat()`` instead of ``.strftime``. Reading an outdated
state file will still work on Python 3.11+, but not on earlier versions.

* Use aware datetime object in x509.CertificateBuilder
This commit is contained in:
Paul Ganssle 2023-08-31 04:28:31 -04:00 committed by GitHub
parent b91cbd1661
commit f612503035
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 18 additions and 15 deletions

1
news/12005.bugfix.rst Normal file
View file

@ -0,0 +1 @@
Removed uses of ``datetime.datetime.utcnow`` from non-vendored code.

View file

@ -28,8 +28,7 @@ from pip._internal.utils.entrypoints import (
from pip._internal.utils.filesystem import adjacent_tmp_file, check_path_owner, replace from pip._internal.utils.filesystem import adjacent_tmp_file, check_path_owner, replace
from pip._internal.utils.misc import ensure_dir from pip._internal.utils.misc import ensure_dir
_DATE_FMT = "%Y-%m-%dT%H:%M:%SZ" _WEEK = datetime.timedelta(days=7)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -73,12 +72,10 @@ class SelfCheckState:
if "pypi_version" not in self._state: if "pypi_version" not in self._state:
return None return None
seven_days_in_seconds = 7 * 24 * 60 * 60
# Determine if we need to refresh the state # Determine if we need to refresh the state
last_check = datetime.datetime.strptime(self._state["last_check"], _DATE_FMT) last_check = datetime.datetime.fromisoformat(self._state["last_check"])
seconds_since_last_check = (current_time - last_check).total_seconds() time_since_last_check = current_time - last_check
if seconds_since_last_check > seven_days_in_seconds: if time_since_last_check > _WEEK:
return None return None
return self._state["pypi_version"] return self._state["pypi_version"]
@ -100,7 +97,7 @@ class SelfCheckState:
# Include the key so it's easy to tell which pip wrote the # Include the key so it's easy to tell which pip wrote the
# file. # file.
"key": self.key, "key": self.key,
"last_check": current_time.strftime(_DATE_FMT), "last_check": current_time.isoformat(),
"pypi_version": pypi_version, "pypi_version": pypi_version,
} }
@ -229,7 +226,7 @@ def pip_self_version_check(session: PipSession, options: optparse.Values) -> Non
try: try:
upgrade_prompt = _self_version_check_logic( upgrade_prompt = _self_version_check_logic(
state=SelfCheckState(cache_dir=options.cache_dir), state=SelfCheckState(cache_dir=options.cache_dir),
current_time=datetime.datetime.utcnow(), current_time=datetime.datetime.now(datetime.timezone.utc),
local_version=installed_dist.version, local_version=installed_dist.version,
get_remote_version=functools.partial( get_remote_version=functools.partial(
_get_current_remote_pip_version, session, options _get_current_remote_pip_version, session, options

View file

@ -1,4 +1,4 @@
from datetime import datetime, timedelta from datetime import datetime, timedelta, timezone
from typing import Tuple from typing import Tuple
from cryptography import x509 from cryptography import x509
@ -23,8 +23,8 @@ def make_tls_cert(hostname: str) -> Tuple[x509.Certificate, rsa.RSAPrivateKey]:
.issuer_name(issuer) .issuer_name(issuer)
.public_key(key.public_key()) .public_key(key.public_key())
.serial_number(x509.random_serial_number()) .serial_number(x509.random_serial_number())
.not_valid_before(datetime.utcnow()) .not_valid_before(datetime.now(timezone.utc))
.not_valid_after(datetime.utcnow() + timedelta(days=10)) .not_valid_after(datetime.now(timezone.utc) + timedelta(days=10))
.add_extension( .add_extension(
x509.SubjectAlternativeName([x509.DNSName(hostname)]), x509.SubjectAlternativeName([x509.DNSName(hostname)]),
critical=False, critical=False,

View file

@ -49,7 +49,9 @@ def test_pip_self_version_check_calls_underlying_implementation(
mocked_state.assert_called_once_with(cache_dir=str(tmpdir)) mocked_state.assert_called_once_with(cache_dir=str(tmpdir))
mocked_function.assert_called_once_with( mocked_function.assert_called_once_with(
state=mocked_state(cache_dir=str(tmpdir)), state=mocked_state(cache_dir=str(tmpdir)),
current_time=datetime.datetime(1970, 1, 2, 11, 0, 0), current_time=datetime.datetime(
1970, 1, 2, 11, 0, 0, tzinfo=datetime.timezone.utc
),
local_version=ANY, local_version=ANY,
get_remote_version=ANY, get_remote_version=ANY,
) )
@ -167,7 +169,10 @@ class TestSelfCheckState:
# WHEN # WHEN
state = self_outdated_check.SelfCheckState(cache_dir=str(cache_dir)) state = self_outdated_check.SelfCheckState(cache_dir=str(cache_dir))
state.set("1.0.0", datetime.datetime(2000, 1, 1, 0, 0, 0)) state.set(
"1.0.0",
datetime.datetime(2000, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc),
)
# THEN # THEN
assert state._statefile_path == os.fspath(expected_path) assert state._statefile_path == os.fspath(expected_path)
@ -175,6 +180,6 @@ class TestSelfCheckState:
contents = expected_path.read_text() contents = expected_path.read_text()
assert json.loads(contents) == { assert json.loads(contents) == {
"key": sys.prefix, "key": sys.prefix,
"last_check": "2000-01-01T00:00:00Z", "last_check": "2000-01-01T00:00:00+00:00",
"pypi_version": "1.0.0", "pypi_version": "1.0.0",
} }