Compare commits

..

1 Commits

Author SHA1 Message Date
3c5bb5b772 import CS awscli2-2.15.31-3.el9 2024-09-30 16:52:32 +00:00
14 changed files with 62 additions and 1503 deletions

1
.awscli2.metadata Normal file
View File

@ -0,0 +1 @@
225e5e6a2aa2145d106cc20a4dacee47789b8830 SOURCES/aws-cli-2.15.31.tar.gz

43
.gitignore vendored
View File

@ -1,42 +1 @@
/aws-cli-2.11.16.tar.gz
/aws-cli-2.11.17.tar.gz
/aws-cli-2.11.18.tar.gz
/aws-cli-2.11.19.tar.gz
/aws-cli-2.11.20.tar.gz
/aws-cli-2.11.21.tar.gz
/aws-cli-2.11.22.tar.gz
/aws-cli-2.11.23.tar.gz
/aws-cli-2.11.24.tar.gz
/aws-cli-2.11.25.tar.gz
/aws-cli-2.11.26.tar.gz
/aws-cli-2.11.27.tar.gz
/aws-cli-2.12.0.tar.gz
/aws-cli-2.13.3.tar.gz
/aws-cli-2.13.4.tar.gz
/aws-cli-2.13.6.tar.gz
/aws-cli-2.13.7.tar.gz
/aws-cli-2.13.9.tar.gz
/aws-cli-2.13.11.tar.gz
/aws-cli-2.13.12.tar.gz
/aws-cli-2.13.17.tar.gz
/aws-cli-2.13.23.tar.gz
/aws-cli-2.13.26.tar.gz
/aws-cli-2.13.28.tar.gz
/aws-cli-2.13.30.tar.gz
/aws-cli-2.13.36.tar.gz
/aws-cli-2.13.37.tar.gz
/aws-cli-2.15.1.tar.gz
/aws-cli-2.15.2.tar.gz
/aws-cli-2.15.10.tar.gz
/aws-cli-2.15.31.tar.gz
/aws-cli-2.15.30.tar.gz
/aws-cli-2.15.31.tar.gz
/aws-cli-2.16.8.tar.gz
/aws-cli-2.17.0.tar.gz
/aws-cli-2.17.1.tar.gz
/aws-cli-2.17.2.tar.gz
/aws-cli-2.17.6.tar.gz
/aws-cli-2.17.13.tar.gz
/aws-cli-2.17.18.tar.gz
/aws-cli-2.22.9.tar.gz
/aws-cli-2.27.0.tar.gz
SOURCES/aws-cli-2.15.31.tar.gz

View File

@ -1,20 +0,0 @@
upstream_package_name: awscli
downstream_package_name: awscli2
upstream_project_url: https://github.com/aws/aws-cli
# react only to v2 tags
upstream_tag_include: "^2\\..+"
specfile_path: awscli2.spec
jobs:
- job: pull_from_upstream
trigger: release
dist_git_branches:
- fedora-rawhide
- job: koji_build
trigger: commit
dist_git_branches:
- fedora-rawhide

View File

@ -1,38 +0,0 @@
From 4b5762bb17f172d9f9e058df8908651856ff4a69 Mon Sep 17 00:00:00 2001
From: Adam Williamson <awilliam@redhat.com>
Date: Thu, 13 Jun 2024 10:33:42 -0700
Subject: [PATCH] Bump the ceiling for botocore memory leak tests to 15 MiB
See https://github.com/boto/botocore/issues/3205 for the
background on this. In rebuilding awscli2 for Python 3.13 in
Fedora Rawhide, we found that two of these tests fail because
they now top out around 11MiB of memory usage, rather than
around 1.6MiB. We don't understand why this is yet, but it's not
a memory *leak*, so bumping the ceiling seems appropriate. I'm
sending this upstream so I have a reference for the downstream
package and to raise awareness of the issue, but the correct fix
may be something else.
Signed-off-by: Adam Williamson <awilliam@redhat.com>
---
tests/functional/botocore/leak/test_resource_leaks.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/functional/botocore/leak/test_resource_leaks.py b/tests/functional/botocore/leak/test_resource_leaks.py
index df1c4fe7f..73027725f 100644
--- a/tests/functional/botocore/leak/test_resource_leaks.py
+++ b/tests/functional/botocore/leak/test_resource_leaks.py
@@ -22,8 +22,8 @@ class TestDoesNotLeakMemory(BaseClientDriverTest):
# a substantial amount of time to the total test run time.
INJECT_DUMMY_CREDS = True
# We're making up numbers here, but let's say arbitrarily
- # that the memory can't increase by more than 10MB.
- MAX_GROWTH_BYTES = 10 * 1024 * 1024
+ # that the memory can't increase by more than 15MB.
+ MAX_GROWTH_BYTES = 15 * 1024 * 1024
def test_create_single_client_memory_constant(self):
self.cmd('create_client', 's3')
--
2.45.2

View File

@ -1,3 +0,0 @@
# awscli2
The awscli2 package

View File

@ -1,3 +0,0 @@
This repository is maintained by packit.
https://packit.dev/
The file was generated using packit 0.99.0.post1.dev18+g4850a935.

View File

@ -1,82 +1,67 @@
%bcond tests 1
%global pkgname aws-cli
Name: awscli2
Version: 2.27.0
Release: %autorelease
Version: 2.15.31
Release: 3%{?dist}
Summary: Universal Command Line Environment for AWS, version 2
# all files are licensed under Apache-2.0, except:
# - awscli/topictags.py is MIT
# - awscli/botocore/vendored/six.py is MIT
License: Apache-2.0 AND MIT
URL: https://github.com/aws/aws-cli/tree/v2
Source0: https://github.com/aws/aws-cli/archive/%{version}/%{pkgname}-%{version}.tar.gz
# adapt to whitespace formatting changes and removal of OrderedDict in ruamel-yaml
Patch0: ruamel-yaml-0.17.32.patch
# fix Python 3.12 incompatibilities
Patch1: python312.patch
# Bump ceiling for botocore memory leak tests
# https://github.com/aws/aws-cli/pull/8744
# https://github.com/boto/botocore/issues/3205
Patch2: 0001-Bump-the-ceiling-for-botocore-memory-leak-tests-to-1.patch
# compatibility fixes for urllib3 v2
Patch3: urllib3-v2.patch
# fix Python 3.14 incompatibilities
Patch4: python314.patch
BuildArch: noarch
BuildRequires: python%{python3_pkgversion}-devel
BuildRequires: python3-devel
BuildRequires: python-unversioned-command
BuildRequires: procps-ng
# Needed for paging output from awscli2. See RHEL-14523.
Requires: less
Recommends: groff
Provides: bundled(python3dist(botocore)) = 2.0.0
Provides: bundled(python3dist(s3transfer)) = 0.5.1
Provides: awscli = %{version}-%{release}
Obsoletes: awscli < 2
# provide an upgrade path from awscli-2 (Amazon Linux)
Provides: awscli-2 = %{version}-%{release}
Obsoletes: awscli-2 < %{version}-%{release}
# python-awscrt does not build on i686 nor s390x
ExcludeArch: %{ix86} s390x
# python-awscrt does not build on s390x
ExcludeArch: s390x
%description
This package provides version 2 of the unified command line
interface to Amazon Web Services.
%prep
%autosetup -p1 -n %{pkgname}-%{version}
# fix permissions
find awscli/examples/ -type f -name '*.rst' -executable -exec chmod -x '{}' +
# remove version caps on dependencies
sed -i 's/,<=\?[^"]*"/"/' pyproject.toml
# loosen awscrt version requirement
sed -i 's/awscrt==/awscrt>=/' pyproject.toml
# remove zipp dependency
sed -i "/zipp<3.21.0/d" pyproject.toml
# use unittest.mock
find -type f -name '*.py' -exec sed \
-e 's/^\( *\)import mock$/\1from unittest import mock/' \
-e 's/^\( *\)from mock import mock/\1from unittest import mock/' \
-e 's/^\( *\)from mock import/\1from unittest.mock import/' \
-i '{}' +
# Fedora does not run coverage tests.
# mock is deprecated in Fedora. We use unittest.mock.
# RHEL does not run coverage tests.
# mock is deprecated in RHEL. We use unittest.mock.
# pip-tools is not used directly by the unit tests.
# pytest-xdist is unwanted in RHEL.
sed \
@ -87,52 +72,63 @@ sed \
-e '/pytest-cov/d' \
%{?rhel:-e '/pytest-xdist/d'} \
requirements-test.txt > _requirements-test.txt
%generate_buildrequires
%pyproject_buildrequires _requirements-test.txt
%build
%pyproject_wheel
%install
%pyproject_install
%pyproject_save_files awscli
# remove unnecessary scripts
rm -vf %{buildroot}%{_bindir}/{aws_bash_completer,aws_zsh_completer.sh,aws.cmd}
# install shell completion
install -Dpm0644 bin/aws_bash_completer \
%{buildroot}%{bash_completions_dir}/aws
%{buildroot}%{_datadir}/bash-completion/completions/aws
install -Dpm0644 bin/aws_zsh_completer.sh \
%{buildroot}%{zsh_completions_dir}/_awscli
%{buildroot}%{_datadir}/zsh/site-functions/_awscli
%check
# it appears that some tests modify the environment and remove PYTHONPATH
# so it's not passed to botocore cmd-runner, inject it here
sed -i '/self.driver.start(env=env)/i \ \ \ \ \ \ \ \ env["PYTHONPATH"] = "%{buildroot}%{python3_sitelib}"' \
tests/utils/botocore/__init__.py
export TESTS_REMOVE_REPO_ROOT_FROM_PATH=1 TZ=UTC
%if 0%{?rhel}
export OPENSSL_ENABLE_SHA1_SIGNATURES=yes
%endif
%pytest --verbose %{!?rhel:--numprocesses=auto --dist=loadfile --maxprocesses=4} \
--disable-pytest-warnings -Wd \
tests/unit tests/functional \
--ignore tests/functional/autocomplete/test_completion_files.py \
--ignore tests/functional/botocore/test_waiter_config.py
%files -f %{pyproject_files}
%license LICENSE.txt
%doc README.rst
%{_bindir}/aws
%{_bindir}/aws_completer
%{bash_completions_dir}/aws
%{zsh_completions_dir}/_awscli
%{_datadir}/bash-completion/completions/aws
%{_datadir}/zsh/site-functions/_awscli
%changelog
%autochangelog
* Fri May 31 2024 Major Hayden <major@redhat.com> - 2.15.31-3
- Add less to install requirements for paging output. Resolves RHEL-14523.
* Thu May 09 2024 Major Hayden <major@redhat.com> - 2.15.31-2
- Remove colorama patches
- Bring in the latest updates from Fedora
* Wed Jan 31 2024 Major Hayden <major@redhat.com> - 2.15.31-1
- Initial RHEL 9 package.

View File

@ -1,6 +0,0 @@
--- !Policy
product_versions:
- rhel-10
decision_context: osci_compose_gate
rules:
- !PassingTestCaseRule {test_case_name: osci.brew-build.tier0.functional}

View File

@ -1,934 +0,0 @@
diff --git a/awscli/botocore/auth.py b/awscli/botocore/auth.py
index 19fbe36..efb1b02 100644
--- a/awscli/botocore/auth.py
+++ b/awscli/botocore/auth.py
@@ -419,7 +419,7 @@ class SigV4Auth(BaseSigner):
def add_auth(self, request):
if self.credentials is None:
raise NoCredentialsError()
- datetime_now = datetime.datetime.utcnow()
+ datetime_now = datetime.datetime.now(datetime.timezone.utc)
request.context['timestamp'] = datetime_now.strftime(SIGV4_TIMESTAMP)
# This could be a retry. Make sure the previous
# authorization header is removed first.
@@ -465,7 +465,7 @@ class SigV4Auth(BaseSigner):
if 'Date' in request.headers:
del request.headers['Date']
datetime_timestamp = datetime.datetime.strptime(
- request.context['timestamp'], SIGV4_TIMESTAMP
+ request.context['timestamp'], SIGV4_TIMESTAMP[:-1] + '%z'
)
request.headers['Date'] = formatdate(
int(calendar.timegm(datetime_timestamp.timetuple()))
@@ -557,7 +557,7 @@ class S3ExpressPostAuth(S3ExpressAuth):
REQUIRES_IDENTITY_CACHE = True
def add_auth(self, request):
- datetime_now = datetime.datetime.utcnow()
+ datetime_now = datetime.datetime.now(datetime.timezone.utc)
request.context['timestamp'] = datetime_now.strftime(SIGV4_TIMESTAMP)
fields = {}
@@ -818,7 +818,7 @@ class S3SigV4PostAuth(SigV4Auth):
"""
def add_auth(self, request):
- datetime_now = datetime.datetime.utcnow()
+ datetime_now = datetime.datetime.now(datetime.timezone.utc)
request.context['timestamp'] = datetime_now.strftime(SIGV4_TIMESTAMP)
fields = {}
diff --git a/awscli/botocore/crt/auth.py b/awscli/botocore/crt/auth.py
index 2b96c7e..86104f3 100644
--- a/awscli/botocore/crt/auth.py
+++ b/awscli/botocore/crt/auth.py
@@ -56,11 +56,7 @@ class CrtSigV4Auth(BaseSigner):
if self.credentials is None:
raise NoCredentialsError()
- # Use utcnow() because that's what gets mocked by tests, but set
- # timezone because CRT assumes naive datetime is local time.
- datetime_now = datetime.datetime.utcnow().replace(
- tzinfo=datetime.timezone.utc
- )
+ datetime_now = datetime.datetime.now(datetime.timezone.utc)
# Use existing 'X-Amz-Content-SHA256' header if able
existing_sha256 = self._get_existing_sha256(request)
@@ -254,11 +250,7 @@ class CrtSigV4AsymAuth(BaseSigner):
if self.credentials is None:
raise NoCredentialsError()
- # Use utcnow() because that's what gets mocked by tests, but set
- # timezone because CRT assumes naive datetime is local time.
- datetime_now = datetime.datetime.utcnow().replace(
- tzinfo=datetime.timezone.utc
- )
+ datetime_now = datetime.datetime.now(datetime.timezone.utc)
# Use existing 'X-Amz-Content-SHA256' header if able
existing_sha256 = self._get_existing_sha256(request)
diff --git a/awscli/botocore/signers.py b/awscli/botocore/signers.py
index 02e759b..5e894ae 100644
--- a/awscli/botocore/signers.py
+++ b/awscli/botocore/signers.py
@@ -713,7 +713,7 @@ class S3PostPresigner:
policy = {}
# Create an expiration date for the policy
- datetime_now = datetime.datetime.utcnow()
+ datetime_now = datetime.datetime.now(datetime.timezone.utc)
expire_date = datetime_now + datetime.timedelta(seconds=expires_in)
policy['expiration'] = expire_date.strftime(botocore.auth.ISO8601)
diff --git a/awscli/botocore/utils.py b/awscli/botocore/utils.py
index 78efaba..9d7cd1d 100644
--- a/awscli/botocore/utils.py
+++ b/awscli/botocore/utils.py
@@ -608,7 +608,7 @@ class InstanceMetadataFetcher(IMDSFetcher):
return
try:
expiration = datetime.datetime.strptime(
- expiration, "%Y-%m-%dT%H:%M:%SZ"
+ expiration, "%Y-%m-%dT%H:%M:%S%z"
)
refresh_interval = self._config.get(
"ec2_credential_refresh_window", 60 * 10
@@ -616,7 +616,7 @@ class InstanceMetadataFetcher(IMDSFetcher):
refresh_interval_with_jitter = refresh_interval + random.randint(
120, 600
)
- current_time = datetime.datetime.utcnow()
+ current_time = datetime.datetime.now(datetime.timezone.utc)
refresh_offset = datetime.timedelta(
seconds=refresh_interval_with_jitter
)
diff --git a/awscli/compat.py b/awscli/compat.py
index e1d58bd..cd496d3 100644
--- a/awscli/compat.py
+++ b/awscli/compat.py
@@ -24,6 +24,7 @@ import shlex
import signal
import sys
import urllib.parse as urlparse
+import urllib.request
import zipfile
from configparser import RawConfigParser
from functools import partial
diff --git a/awscli/customizations/cloudformation/deployer.py b/awscli/customizations/cloudformation/deployer.py
index a5c512f..8783ebb 100644
--- a/awscli/customizations/cloudformation/deployer.py
+++ b/awscli/customizations/cloudformation/deployer.py
@@ -15,7 +15,7 @@ import collections
import logging
import sys
import time
-from datetime import datetime
+from datetime import datetime, timezone
import botocore
@@ -98,7 +98,7 @@ class Deployer:
:return:
"""
- now = datetime.utcnow().isoformat()
+ now = datetime.now(timezone.utc).isoformat()
description = f"Created by AWS CLI at {now} UTC"
# Each changeset will get a unique name based on time
diff --git a/awscli/customizations/cloudtrail/validation.py b/awscli/customizations/cloudtrail/validation.py
index f4229ba..1aa960c 100644
--- a/awscli/customizations/cloudtrail/validation.py
+++ b/awscli/customizations/cloudtrail/validation.py
@@ -18,7 +18,7 @@ import logging
import re
import sys
import zlib
-from datetime import datetime, timedelta
+from datetime import datetime, timedelta, timezone
from zlib import error as ZLibError
from awscrt.crypto import RSA, RSASignatureAlgorithm
@@ -444,7 +444,7 @@ class DigestTraverser:
:param end_date: Date to stop validating at (inclusive).
"""
if end_date is None:
- end_date = datetime.utcnow()
+ end_date = datetime.now(timezone.utc)
end_date = normalize_date(end_date)
start_date = normalize_date(start_date)
bucket = self.starting_bucket
@@ -830,7 +830,7 @@ class CloudTrailValidateLogs(BasicCommand):
if args.end_time:
self.end_time = normalize_date(parse_date(args.end_time))
else:
- self.end_time = normalize_date(datetime.utcnow())
+ self.end_time = normalize_date(datetime.now(timezone.utc))
if self.start_time > self.end_time:
raise ParamValidationError(
'Invalid time range specified: start-time must '
diff --git a/awscli/customizations/codecommit.py b/awscli/customizations/codecommit.py
index b001562..cb9e757 100644
--- a/awscli/customizations/codecommit.py
+++ b/awscli/customizations/codecommit.py
@@ -159,7 +159,7 @@ class CodeCommitGetCommand(BasicCommand):
request = AWSRequest()
request.url = url_to_sign
request.method = 'GIT'
- now = datetime.datetime.utcnow()
+ now = datetime.datetime.now(datetime.timezone.utc)
request.context['timestamp'] = now.strftime('%Y%m%dT%H%M%S')
split = urlsplit(request.url)
# we don't want to include the port number in the signature
diff --git a/awscli/customizations/codedeploy/push.py b/awscli/customizations/codedeploy/push.py
index bdde82e..3281ce4 100644
--- a/awscli/customizations/codedeploy/push.py
+++ b/awscli/customizations/codedeploy/push.py
@@ -16,7 +16,7 @@ import os
import sys
import tempfile
import zipfile
-from datetime import datetime
+from datetime import datetime, timezone
from botocore.exceptions import ClientError
@@ -131,7 +131,7 @@ class Push(BasicCommand):
)
if not parsed_args.description:
parsed_args.description = (
- f'Uploaded by AWS CLI {datetime.utcnow().isoformat()} UTC'
+ f'Uploaded by AWS CLI {datetime.now(timezone.utc).isoformat()} UTC'
)
def _push(self, params):
diff --git a/awscli/customizations/datapipeline/__init__.py b/awscli/customizations/datapipeline/__init__.py
index 5665769..d197339 100644
--- a/awscli/customizations/datapipeline/__init__.py
+++ b/awscli/customizations/datapipeline/__init__.py
@@ -12,7 +12,7 @@
# language governing permissions and limitations under the License.
import json
-from datetime import datetime, timedelta
+from datetime import datetime, timedelta, timezone
from awscli.arguments import CustomArgument
from awscli.customizations.commands import BasicCommand
@@ -197,7 +197,7 @@ class QueryArgBuilder:
def __init__(self, current_time=None):
if current_time is None:
- current_time = datetime.utcnow()
+ current_time = datetime.now(timezone.utc)
self.current_time = current_time
def build_query(self, parsed_args):
diff --git a/awscli/customizations/ec2/bundleinstance.py b/awscli/customizations/ec2/bundleinstance.py
index 240540f..8dc2e22 100644
--- a/awscli/customizations/ec2/bundleinstance.py
+++ b/awscli/customizations/ec2/bundleinstance.py
@@ -129,7 +129,7 @@ def _generate_policy(params):
# Called if there is no policy supplied by the user.
# Creates a policy that provides access for 24 hours.
delta = datetime.timedelta(hours=24)
- expires = datetime.datetime.utcnow() + delta
+ expires = datetime.datetime.now(datetime.timezone.utc) + delta
expires_iso = expires.strftime("%Y-%m-%dT%H:%M:%S.%fZ")
policy = POLICY.format(
expires=expires_iso, bucket=params['Bucket'], prefix=params['Prefix']
diff --git a/awscli/customizations/eks/get_token.py b/awscli/customizations/eks/get_token.py
index 00fc4d3..ee8c74c 100644
--- a/awscli/customizations/eks/get_token.py
+++ b/awscli/customizations/eks/get_token.py
@@ -14,7 +14,7 @@ import base64
import json
import os
import sys
-from datetime import datetime, timedelta
+from datetime import datetime, timedelta, timezone
import botocore
from botocore.model import ServiceId
@@ -105,7 +105,7 @@ class GetTokenCommand(BasicCommand):
]
def get_expiration_time(self):
- token_expiration = datetime.utcnow() + timedelta(
+ token_expiration = datetime.now(timezone.utc) + timedelta(
minutes=TOKEN_EXPIRATION_MINS
)
return token_expiration.strftime('%Y-%m-%dT%H:%M:%SZ')
diff --git a/awscli/customizations/logs/tail.py b/awscli/customizations/logs/tail.py
index e22facd..9b464b4 100644
--- a/awscli/customizations/logs/tail.py
+++ b/awscli/customizations/logs/tail.py
@@ -10,11 +10,12 @@
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
+import functools
import json
import re
import time
from collections import defaultdict
-from datetime import datetime, timedelta
+from datetime import datetime, timedelta, timezone
import colorama
from botocore.utils import datetime2timestamp, parse_timestamp
@@ -266,7 +267,7 @@ class TimestampUtils:
def __init__(self, now=None):
self._now = now
if now is None:
- self._now = datetime.utcnow
+ self._now = functools.partial(datetime.now, timezone.utc)
def to_epoch_millis(self, timestamp):
re_match = self._RELATIVE_TIMESTAMP_REGEX.match(timestamp)
diff --git a/awscli/customizations/opsworks.py b/awscli/customizations/opsworks.py
index ac23cd5..490f44d 100644
--- a/awscli/customizations/opsworks.py
+++ b/awscli/customizations/opsworks.py
@@ -566,7 +566,7 @@ class OpsWorksRegister(BasicCommand):
"Resource": arn,
}
if timeout is not None:
- valid_until = datetime.datetime.utcnow() + timeout
+ valid_until = datetime.datetime.now(datetime.timezone.utc) + timeout
statement["Condition"] = {
"DateLessThan": {
"aws:CurrentTime": valid_until.strftime(
diff --git a/tests/functional/botocore/test_credentials.py b/tests/functional/botocore/test_credentials.py
index 7703df6..1497e11 100644
--- a/tests/functional/botocore/test_credentials.py
+++ b/tests/functional/botocore/test_credentials.py
@@ -19,7 +19,7 @@ import tempfile
import threading
import time
import uuid
-from datetime import datetime, timedelta
+from datetime import datetime, timedelta, timezone
import pytest
from botocore import UNSIGNED
@@ -61,8 +61,8 @@ from tests import (
unittest,
)
-TIME_IN_ONE_HOUR = datetime.utcnow() + timedelta(hours=1)
-TIME_IN_SIX_MONTHS = datetime.utcnow() + timedelta(hours=4320)
+TIME_IN_ONE_HOUR = datetime.now(timezone.utc) + timedelta(hours=1)
+TIME_IN_SIX_MONTHS = datetime.now(timezone.utc) + timedelta(hours=4320)
class TestCredentialRefreshRaces(unittest.TestCase):
diff --git a/tests/functional/botocore/test_ec2.py b/tests/functional/botocore/test_ec2.py
index 81f4b76..39423aa 100644
--- a/tests/functional/botocore/test_ec2.py
+++ b/tests/functional/botocore/test_ec2.py
@@ -92,14 +92,14 @@ class TestCopySnapshotCustomization(BaseSessionTest):
'<snapshotId>%s</snapshotId>\n'
'</CopySnapshotResponse>\n'
)
- self.now = datetime.datetime(2011, 9, 9, 23, 36)
+ self.now = datetime.datetime(2011, 9, 9, 23, 36, tzinfo=datetime.timezone.utc)
self.datetime_patch = mock.patch.object(
botocore.auth.datetime,
'datetime',
mock.Mock(wraps=datetime.datetime),
)
self.mocked_datetime = self.datetime_patch.start()
- self.mocked_datetime.utcnow.return_value = self.now
+ self.mocked_datetime.now.return_value = self.now
def tearDown(self):
super().tearDown()
diff --git a/tests/functional/botocore/test_lex.py b/tests/functional/botocore/test_lex.py
index cded9c0..000f50d 100644
--- a/tests/functional/botocore/test_lex.py
+++ b/tests/functional/botocore/test_lex.py
@@ -10,7 +10,7 @@
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
-from datetime import datetime
+from datetime import datetime, timezone
from tests import BaseSessionTest, ClientHTTPStubber, mock
@@ -31,10 +31,10 @@ class TestLex(BaseSessionTest):
'inputStream': b'',
}
- timestamp = datetime(2017, 3, 22, 0, 0)
+ timestamp = datetime(2017, 3, 22, 0, 0, tzinfo=timezone.utc)
with mock.patch('botocore.auth.datetime') as _datetime:
- _datetime.datetime.utcnow.return_value = timestamp
+ _datetime.datetime.now.return_value = timestamp
self.http_stubber.add_response(body=b'{}')
with self.http_stubber:
self.client.post_content(**params)
diff --git a/tests/functional/botocore/test_s3express.py b/tests/functional/botocore/test_s3express.py
index 91ec532..1a516d2 100644
--- a/tests/functional/botocore/test_s3express.py
+++ b/tests/functional/botocore/test_s3express.py
@@ -108,7 +108,6 @@ class TestS3ExpressAuth:
class TestS3ExpressIdentityCache:
def test_default_s3_express_cache(self, default_s3_client, mock_datetime):
mock_datetime.now.return_value = DATE
- mock_datetime.utcnow.return_value = DATE
identity_cache = S3ExpressIdentityCache(
default_s3_client,
@@ -126,7 +125,6 @@ class TestS3ExpressIdentityCache:
self, default_s3_client, mock_datetime
):
mock_datetime.now.return_value = DATE
- mock_datetime.utcnow.return_value = DATE
bucket = 'my_bucket'
identity_cache = S3ExpressIdentityCache(
@@ -151,7 +149,6 @@ class TestS3ExpressIdentityCache:
self, default_s3_client, mock_datetime
):
mock_datetime.now.return_value = DATE
- mock_datetime.utcnow.return_value = DATE
bucket = 'my_bucket'
other_bucket = 'other_bucket'
@@ -204,7 +201,7 @@ class TestS3ExpressRequests:
)
def test_create_bucket(self, default_s3_client, mock_datetime):
- mock_datetime.utcnow.return_value = DATE
+ mock_datetime.now.return_value = DATE
with ClientHTTPStubber(default_s3_client) as stubber:
stubber.add_response()
@@ -228,7 +225,6 @@ class TestS3ExpressRequests:
self._assert_standard_sigv4_signature(stubber.requests[0].headers)
def test_get_object(self, default_s3_client, mock_datetime):
- mock_datetime.utcnow.return_value = DATE
mock_datetime.now.return_value = DATE
with ClientHTTPStubber(default_s3_client) as stubber:
@@ -250,7 +246,6 @@ class TestS3ExpressRequests:
def test_cache_with_multiple_requests(
self, default_s3_client, mock_datetime
):
- mock_datetime.utcnow.return_value = DATE
mock_datetime.now.return_value = DATE
with ClientHTTPStubber(default_s3_client) as stubber:
@@ -275,7 +270,6 @@ class TestS3ExpressRequests:
def test_delete_objects_injects_correct_checksum(
self, default_s3_client, mock_datetime
):
- mock_datetime.utcnow.return_value = DATE
mock_datetime.now.return_value = DATE
with ClientHTTPStubber(default_s3_client) as stubber:
diff --git a/tests/functional/botocore/test_sts.py b/tests/functional/botocore/test_sts.py
index 6bf343e..407ebab 100644
--- a/tests/functional/botocore/test_sts.py
+++ b/tests/functional/botocore/test_sts.py
@@ -11,7 +11,7 @@
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
import re
-from datetime import datetime
+from datetime import datetime, timezone
from botocore.config import Config
from botocore.stub import Stubber
@@ -32,9 +32,9 @@ class TestSTSPresignedUrl(BaseSessionTest):
self.stubber.activate()
def test_presigned_url_contains_no_content_type(self):
- timestamp = datetime(2017, 3, 22, 0, 0)
+ timestamp = datetime(2017, 3, 22, 0, 0, tzinfo=timezone.utc)
with mock.patch('botocore.auth.datetime') as _datetime:
- _datetime.datetime.utcnow.return_value = timestamp
+ _datetime.datetime.now.return_value = timestamp
url = self.client.generate_presigned_url('get_caller_identity', {})
# There should be no 'content-type' in x-amz-signedheaders
diff --git a/tests/functional/dsql/test_generate_db_auth_token.py b/tests/functional/dsql/test_generate_db_auth_token.py
index 2b48453..39871ab 100644
--- a/tests/functional/dsql/test_generate_db_auth_token.py
+++ b/tests/functional/dsql/test_generate_db_auth_token.py
@@ -50,7 +50,7 @@ class TestGenerateDBConnectAuthToken(BaseTestGenerateDBConnectAuthToken):
clock = datetime.datetime(2024, 11, 7, 17, 39, 33, tzinfo=tzutc())
with mock.patch('datetime.datetime') as dt:
- dt.utcnow.return_value = clock
+ dt.now.return_value = clock
stdout, _, _ = self.run_cmd(command, expected_rc=0)
# Expected hashes are always the same as session variables come from the BaseAwsCommandParamsTest class
@@ -79,7 +79,7 @@ class TestGenerateDBConnectAuthToken(BaseTestGenerateDBConnectAuthToken):
clock = datetime.datetime(2024, 11, 7, 17, 39, 33, tzinfo=tzutc())
with mock.patch('datetime.datetime') as dt:
- dt.utcnow.return_value = clock
+ dt.now.return_value = clock
stdout, _, _ = self.run_cmd(command, expected_rc=252)
@@ -92,7 +92,7 @@ class TestGenerateDBConnectAdminAuthToken(BaseTestGenerateDBConnectAuthToken):
clock = datetime.datetime(2024, 11, 7, 17, 39, 33, tzinfo=tzutc())
with mock.patch('datetime.datetime') as dt:
- dt.utcnow.return_value = clock
+ dt.now.return_value = clock
stdout, _, _ = self.run_cmd(command, expected_rc=0)
# Expected hashes are always the same as session variables come from the BaseAwsCommandParamsTest class
diff --git a/tests/functional/ec2/test_bundle_instance.py b/tests/functional/ec2/test_bundle_instance.py
index 5442929..06747f9 100644
--- a/tests/functional/ec2/test_bundle_instance.py
+++ b/tests/functional/ec2/test_bundle_instance.py
@@ -31,7 +31,7 @@ class TestBundleInstance(BaseAWSCommandParamsTest):
def setUp(self):
super(TestBundleInstance, self).setUp()
- # This mocks out datetime.datetime.utcnow() so that it always
+ # This mocks out datetime.datetime.now() so that it always
# returns the same datetime object. This is because this value
# is embedded into the policy file that is generated and we
# don't what the policy or its signature to change each time
@@ -42,7 +42,7 @@ class TestBundleInstance(BaseAWSCommandParamsTest):
mock.Mock(wraps=datetime.datetime),
)
mocked_datetime = self.datetime_patcher.start()
- mocked_datetime.utcnow.return_value = datetime.datetime(2013, 8, 9)
+ mocked_datetime.now.return_value = datetime.datetime(2013, 8, 9, tzinfo=datetime.timezone.utc)
def tearDown(self):
super(TestBundleInstance, self).tearDown()
diff --git a/tests/functional/ec2instanceconnect/test_opentunnel.py b/tests/functional/ec2instanceconnect/test_opentunnel.py
index cd85b01..e83bf78 100644
--- a/tests/functional/ec2instanceconnect/test_opentunnel.py
+++ b/tests/functional/ec2instanceconnect/test_opentunnel.py
@@ -359,10 +359,10 @@ def request_params_for_describe_eice():
@pytest.fixture
-def datetime_utcnow_patch():
+def datetime_now_patch():
clock = datetime.datetime(2020, 1, 1, 1, 1, 1, tzinfo=tzutc())
with mock.patch('datetime.datetime') as dt:
- dt.utcnow.return_value = clock
+ dt.now.return_value = clock
yield dt
@@ -445,7 +445,7 @@ class TestOpenTunnel:
describe_eice_response,
request_params_for_describe_instance,
request_params_for_describe_eice,
- datetime_utcnow_patch,
+ datetime_now_patch,
):
cli_runner.env["AWS_USE_FIPS_ENDPOINT"] = "false"
cmdline = [
diff --git a/tests/functional/eks/test_get_token.py b/tests/functional/eks/test_get_token.py
index 0e78f9a..5600bdf 100644
--- a/tests/functional/eks/test_get_token.py
+++ b/tests/functional/eks/test_get_token.py
@@ -13,7 +13,7 @@
import base64
import json
import os
-from datetime import datetime
+from datetime import datetime, timezone
from awscli.compat import urlparse
from awscli.testutils import BaseAWSCommandParamsTest, mock
@@ -78,7 +78,7 @@ class TestGetTokenCommand(BaseAWSCommandParamsTest):
@mock.patch('awscli.customizations.eks.get_token.datetime')
def test_get_token(self, mock_datetime):
- mock_datetime.utcnow.return_value = datetime(2019, 10, 23, 23, 0, 0, 0)
+ mock_datetime.now.return_value = datetime(2019, 10, 23, 23, 0, 0, 0, tzinfo=timezone.utc)
cmd = 'eks get-token --cluster-name %s' % self.cluster_name
response = self.run_get_token(cmd)
self.assertEqual(
@@ -96,7 +96,7 @@ class TestGetTokenCommand(BaseAWSCommandParamsTest):
@mock.patch('awscli.customizations.eks.get_token.datetime')
def test_query_nested_object(self, mock_datetime):
- mock_datetime.utcnow.return_value = datetime(2019, 10, 23, 23, 0, 0, 0)
+ mock_datetime.now.return_value = datetime(2019, 10, 23, 23, 0, 0, 0, tzinfo=timezone.utc)
cmd = 'eks get-token --cluster-name %s' % self.cluster_name
cmd += ' --query status'
response = self.run_get_token(cmd)
@@ -119,7 +119,7 @@ class TestGetTokenCommand(BaseAWSCommandParamsTest):
@mock.patch('awscli.customizations.eks.get_token.datetime')
def test_output_text(self, mock_datetime):
- mock_datetime.utcnow.return_value = datetime(2019, 10, 23, 23, 0, 0, 0)
+ mock_datetime.now.return_value = datetime(2019, 10, 23, 23, 0, 0, 0, tzinfo=timezone.utc)
cmd = 'eks get-token --cluster-name %s' % self.cluster_name
cmd += ' --output text'
stdout, _, _ = self.run_cmd(cmd)
@@ -129,7 +129,7 @@ class TestGetTokenCommand(BaseAWSCommandParamsTest):
@mock.patch('awscli.customizations.eks.get_token.datetime')
def test_output_table(self, mock_datetime):
- mock_datetime.utcnow.return_value = datetime(2019, 10, 23, 23, 0, 0, 0)
+ mock_datetime.now.return_value = datetime(2019, 10, 23, 23, 0, 0, 0, tzinfo=timezone.utc)
cmd = 'eks get-token --cluster-name %s' % self.cluster_name
cmd += ' --output table'
stdout, _, _ = self.run_cmd(cmd)
diff --git a/tests/functional/logs/test_tail.py b/tests/functional/logs/test_tail.py
index 0024bd4..8eaf61c 100644
--- a/tests/functional/logs/test_tail.py
+++ b/tests/functional/logs/test_tail.py
@@ -155,7 +155,7 @@ class TestTailCommand(BaseAWSCommandParamsTest):
def test_tail_defaults_to_10m(self):
datetime_mock = mock.Mock(wraps=datetime)
- datetime_mock.utcnow = mock.Mock(
+ datetime_mock.now = mock.Mock(
return_value=datetime(1970, 1, 1, 0, 10, 1, tzinfo=tz.tzutc())
)
with mock.patch(
@@ -182,7 +182,7 @@ class TestTailCommand(BaseAWSCommandParamsTest):
def test_tail_with_relative_since(self):
datetime_mock = mock.Mock(wraps=datetime)
- datetime_mock.utcnow = mock.Mock(
+ datetime_mock.now = mock.Mock(
return_value=datetime(1970, 1, 1, 0, 0, 2, tzinfo=tz.tzutc())
)
with mock.patch(
diff --git a/tests/functional/rds/test_generate_db_auth_token.py b/tests/functional/rds/test_generate_db_auth_token.py
index 4cc562a..4ff83e1 100644
--- a/tests/functional/rds/test_generate_db_auth_token.py
+++ b/tests/functional/rds/test_generate_db_auth_token.py
@@ -50,7 +50,7 @@ class TestGenerateDBAuthToken(BaseAWSCommandParamsTest):
clock = datetime.datetime(2016, 11, 7, 17, 39, 33, tzinfo=tzutc())
with mock.patch('datetime.datetime') as dt:
- dt.utcnow.return_value = clock
+ dt.now.return_value = clock
stdout, _, _ = self.run_cmd(command, expected_rc=0)
expected = (
diff --git a/tests/functional/s3/test_presign_command.py b/tests/functional/s3/test_presign_command.py
index 43ede9a..d315dd3 100644
--- a/tests/functional/s3/test_presign_command.py
+++ b/tests/functional/s3/test_presign_command.py
@@ -22,13 +22,13 @@ from awscli.testutils import (
temporary_file,
)
-# Values used to fix time.time() and datetime.datetime.utcnow()
+# Values used to fix time.time() and datetime.datetime.now()
# so we know the exact values of the signatures generated.
FROZEN_TIMESTAMP = 1471305652
DEFAULT_EXPIRES = 3600
FROZEN_TIME = mock.Mock(return_value=FROZEN_TIMESTAMP)
FROZEN_DATETIME = mock.Mock(
- return_value=datetime.datetime(2016, 8, 18, 14, 33, 3, 0)
+ return_value=datetime.datetime(2016, 8, 18, 14, 33, 3, 0, tzinfo=datetime.timezone.utc)
)
@@ -76,7 +76,7 @@ class TestPresignCommand(BaseAWSCommandParamsTest):
def get_presigned_url_for_cmd(self, cmdline):
with mock.patch('time.time', FROZEN_TIME):
with mock.patch('datetime.datetime') as d:
- d.utcnow = FROZEN_DATETIME
+ d.now = FROZEN_DATETIME
stdout = self.assert_params_for_cmd(cmdline, None)[0].strip()
return stdout
diff --git a/tests/integration/customizations/test_codecommit.py b/tests/integration/customizations/test_codecommit.py
index 7077c08..d904290 100644
--- a/tests/integration/customizations/test_codecommit.py
+++ b/tests/integration/customizations/test_codecommit.py
@@ -12,7 +12,7 @@
# language governing permissions and limitations under the License.
import os
-from datetime import datetime
+from datetime import datetime, timezone
from botocore.awsrequest import AWSRequest
from botocore.credentials import Credentials
@@ -64,7 +64,7 @@ class TestCodeCommitCredentialHelper(unittest.TestCase):
@mock.patch('sys.stdout', new_callable=StringIOWithFileNo)
@mock.patch.object(awscli.customizations.codecommit.datetime, 'datetime')
def test_integration_using_cli_driver(self, dt_mock, stdout_mock):
- dt_mock.utcnow.return_value = datetime(2010, 10, 8)
+ dt_mock.now.return_value = datetime(2010, 10, 8, tzinfo=timezone.utc)
driver = create_clidriver()
entry_point = AWSCLIEntryPoint(driver)
rc = entry_point.main('codecommit credential-helper get'.split())
@@ -83,7 +83,7 @@ class TestCodeCommitCredentialHelper(unittest.TestCase):
@mock.patch('sys.stdout', new_callable=StringIOWithFileNo)
@mock.patch.object(awscli.customizations.codecommit.datetime, 'datetime')
def test_integration_fips_using_cli_driver(self, dt_mock, stdout_mock):
- dt_mock.utcnow.return_value = datetime(2010, 10, 8)
+ dt_mock.now.return_value = datetime(2010, 10, 8, tzinfo=timezone.utc)
driver = create_clidriver()
entry_point = AWSCLIEntryPoint(driver)
rc = entry_point.main('codecommit credential-helper get'.split())
@@ -102,7 +102,7 @@ class TestCodeCommitCredentialHelper(unittest.TestCase):
@mock.patch('sys.stdout', new_callable=StringIOWithFileNo)
@mock.patch.object(awscli.customizations.codecommit.datetime, 'datetime')
def test_integration_vpc_using_cli_driver(self, dt_mock, stdout_mock):
- dt_mock.utcnow.return_value = datetime(2010, 10, 8)
+ dt_mock.now.return_value = datetime(2010, 10, 8, tzinfo=timezone.utc)
driver = create_clidriver()
entry_point = AWSCLIEntryPoint(driver)
rc = entry_point.main('codecommit credential-helper get'.split())
diff --git a/tests/unit/botocore/auth/test_signers.py b/tests/unit/botocore/auth/test_signers.py
index 7effaf3..ff62c77 100644
--- a/tests/unit/botocore/auth/test_signers.py
+++ b/tests/unit/botocore/auth/test_signers.py
@@ -28,10 +28,10 @@ from tests import mock, unittest
class BaseTestWithFixedDate(unittest.TestCase):
def setUp(self):
- self.fixed_date = datetime.datetime(2014, 3, 10, 17, 2, 55, 0)
+ self.fixed_date = datetime.datetime(2014, 3, 10, 17, 2, 55, 0, tzinfo=datetime.timezone.utc)
self.datetime_patch = mock.patch('botocore.auth.datetime.datetime')
self.datetime_mock = self.datetime_patch.start()
- self.datetime_mock.utcnow.return_value = self.fixed_date
+ self.datetime_mock.now.return_value = self.fixed_date
self.datetime_mock.strptime.return_value = self.fixed_date
def tearDown(self):
@@ -379,9 +379,9 @@ class TestSigV4(unittest.TestCase):
'datetime',
mock.Mock(wraps=datetime.datetime),
) as mock_datetime:
- original_utcnow = datetime.datetime(2014, 1, 1, 0, 0)
+ original_now = datetime.datetime(2014, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)
- mock_datetime.utcnow.return_value = original_utcnow
+ mock_datetime.now.return_value = original_now
# Go through the add_auth process once. This will attach
# a timestamp to the request at the beginning of auth.
auth.add_auth(request)
@@ -389,9 +389,8 @@ class TestSigV4(unittest.TestCase):
# Ensure the date is in the Authorization header
self.assertIn('20140101', request.headers['Authorization'])
# Now suppose the utc time becomes the next day all of a sudden
- mock_datetime.utcnow.return_value = datetime.datetime(
- 2014, 1, 2, 0, 0
- )
+ mock_datetime.now.return_value = datetime.datetime(
+ 2014, 1, 2, 0, 0, tzinfo=datetime.timezone.utc)
# Smaller methods like the canonical request and string_to_sign
# should have the timestamp attached to the request in their
# body and not what the time is now mocked as. This is to ensure
@@ -563,8 +562,8 @@ class TestSigV4Presign(BasePresignTest):
mock.Mock(wraps=datetime.datetime),
)
mocked_datetime = self.datetime_patcher.start()
- mocked_datetime.utcnow.return_value = datetime.datetime(
- 2014, 1, 1, 0, 0
+ mocked_datetime.now.return_value = datetime.datetime(
+ 2014, 1, 1, 0, 0, tzinfo=datetime.timezone.utc
)
def tearDown(self):
@@ -780,8 +779,8 @@ class TestS3SigV4Post(BaseS3PresignPostTest):
mock.Mock(wraps=datetime.datetime),
)
mocked_datetime = self.datetime_patcher.start()
- mocked_datetime.utcnow.return_value = datetime.datetime(
- 2014, 1, 1, 0, 0
+ mocked_datetime.now.return_value = datetime.datetime(
+ 2014, 1, 1, 0, 0, tzinfo=datetime.timezone.utc
)
def tearDown(self):
diff --git a/tests/unit/botocore/test_credentials.py b/tests/unit/botocore/test_credentials.py
index feb35d0..70f2b47 100644
--- a/tests/unit/botocore/test_credentials.py
+++ b/tests/unit/botocore/test_credentials.py
@@ -16,7 +16,7 @@ import os
import shutil
import subprocess
import tempfile
-from datetime import datetime, timedelta
+from datetime import datetime, timedelta, timezone
import botocore.exceptions
import botocore.session
@@ -125,7 +125,7 @@ class TestRefreshableCredentials(TestCredentials):
def test_refresh_needed(self):
# The expiry time was set for 30 minutes ago, so if we
- # say the current time is utcnow(), then we should need
+ # say the current time is now(), then we should need
# a refresh.
self.mock_time.return_value = datetime.now(tzlocal())
self.assertTrue(self.creds.refresh_needed())
@@ -313,8 +313,8 @@ class TestAssumeRoleCredentialFetcher(BaseEnvVar):
self.assertEqual(response, expected_response)
def test_retrieves_from_cache(self):
- date_in_future = datetime.utcnow() + timedelta(seconds=1000)
- utc_timestamp = date_in_future.isoformat() + 'Z'
+ date_in_future = datetime.now(timezone.utc) + timedelta(seconds=1000)
+ utc_timestamp = date_in_future.isoformat()
cache_key = '793d6e2f27667ab2da104824407e486bfec24a47'
cache = {
cache_key: {
@@ -793,8 +793,8 @@ class TestAssumeRoleWithWebIdentityCredentialFetcher(BaseEnvVar):
self.assertEqual(response, expected_response)
def test_retrieves_from_cache(self):
- date_in_future = datetime.utcnow() + timedelta(seconds=1000)
- utc_timestamp = date_in_future.isoformat() + 'Z'
+ date_in_future = datetime.now(timezone.utc) + timedelta(seconds=1000)
+ utc_timestamp = date_in_future.isoformat()
cache_key = '793d6e2f27667ab2da104824407e486bfec24a47'
cache = {
cache_key: {
@@ -958,8 +958,8 @@ class TestAssumeRoleWithWebIdentityCredentialProvider(unittest.TestCase):
mock_loader_cls.assert_called_with('/some/path/token.jwt')
def test_assume_role_retrieves_from_cache(self):
- date_in_future = datetime.utcnow() + timedelta(seconds=1000)
- utc_timestamp = date_in_future.isoformat() + 'Z'
+ date_in_future = datetime.now(timezone.utc) + timedelta(seconds=1000)
+ utc_timestamp = date_in_future.isoformat()
cache_key = 'c29461feeacfbed43017d20612606ff76abc073d'
cache = {
@@ -2199,8 +2199,8 @@ class TestAssumeRoleCredentialProvider(unittest.TestCase):
self.assertEqual(expiry_time, '2016-11-06T01:30:00UTC')
def test_assume_role_retrieves_from_cache(self):
- date_in_future = datetime.utcnow() + timedelta(seconds=1000)
- utc_timestamp = date_in_future.isoformat() + 'Z'
+ date_in_future = datetime.now(timezone.utc) + timedelta(seconds=1000)
+ utc_timestamp = date_in_future.isoformat()
self.fake_config['profiles']['development']['role_arn'] = 'myrole'
cache_key = '793d6e2f27667ab2da104824407e486bfec24a47'
@@ -2228,8 +2228,8 @@ class TestAssumeRoleCredentialProvider(unittest.TestCase):
self.assertEqual(creds.token, 'baz-cached')
def test_chain_prefers_cache(self):
- date_in_future = datetime.utcnow() + timedelta(seconds=1000)
- utc_timestamp = date_in_future.isoformat() + 'Z'
+ date_in_future = datetime.now(timezone.utc) + timedelta(seconds=1000)
+ utc_timestamp = date_in_future.isoformat()
# The profile we will be using has a cache entry, but the profile it
# is sourcing from does not. This should result in the cached
diff --git a/tests/unit/botocore/test_signers.py b/tests/unit/botocore/test_signers.py
index b97bf58..ed54e9a 100644
--- a/tests/unit/botocore/test_signers.py
+++ b/tests/unit/botocore/test_signers.py
@@ -686,9 +686,9 @@ class TestS3PostPresigner(BaseSignerTest):
self.datetime_patch = mock.patch('botocore.signers.datetime')
self.datetime_mock = self.datetime_patch.start()
- self.fixed_date = datetime.datetime(2014, 3, 10, 17, 2, 55, 0)
+ self.fixed_date = datetime.datetime(2014, 3, 10, 17, 2, 55, 0, tzinfo=datetime.timezone.utc)
self.fixed_delta = datetime.timedelta(seconds=3600)
- self.datetime_mock.datetime.utcnow.return_value = self.fixed_date
+ self.datetime_mock.datetime.now.return_value = self.fixed_date
self.datetime_mock.timedelta.return_value = self.fixed_delta
def tearDown(self):
@@ -1141,7 +1141,7 @@ class TestGenerateDBAuthToken(BaseSignerTest):
clock = datetime.datetime(2016, 11, 7, 17, 39, 33, tzinfo=tzutc())
with mock.patch('datetime.datetime') as dt:
- dt.utcnow.return_value = clock
+ dt.now.return_value = clock
result = generate_db_auth_token(
self.client, hostname, port, username
)
diff --git a/tests/unit/botocore/test_utils.py b/tests/unit/botocore/test_utils.py
index 7538f02..f9579a3 100644
--- a/tests/unit/botocore/test_utils.py
+++ b/tests/unit/botocore/test_utils.py
@@ -102,7 +102,7 @@ from dateutil.tz import tzoffset, tzutc
from tests import FreezeTime, RawResponse, create_session, mock, unittest
-DATE = datetime.datetime(2021, 12, 10, 00, 00, 00)
+DATE = datetime.datetime(2021, 12, 10, 00, 00, 00, tzinfo=datetime.timezone.utc)
DT_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
@@ -3116,7 +3116,7 @@ class TestInstanceMetadataFetcher(unittest.TestCase):
def _get_datetime(self, dt=None, offset=None, offset_func=operator.add):
if dt is None:
- dt = datetime.datetime.utcnow()
+ dt = datetime.datetime.now(datetime.timezone.utc)
if offset is not None:
dt = offset_func(dt, offset)
diff --git a/tests/unit/customizations/eks/test_get_token.py b/tests/unit/customizations/eks/test_get_token.py
index 7f830b3..0f019c3 100644
--- a/tests/unit/customizations/eks/test_get_token.py
+++ b/tests/unit/customizations/eks/test_get_token.py
@@ -48,7 +48,7 @@ class TestGetTokenCommand(BaseTokenTest):
cmd = GetTokenCommand(self._session)
timestamp = cmd.get_expiration_time()
try:
- datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%SZ')
+ datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%S%z')
except ValueError:
raise ValueError(
"Incorrect data format, should be %Y-%m-%dT%H:%M:%SZ"
diff --git a/tests/unit/customizations/test_opsworks.py b/tests/unit/customizations/test_opsworks.py
index 0712d63..951ad31 100644
--- a/tests/unit/customizations/test_opsworks.py
+++ b/tests/unit/customizations/test_opsworks.py
@@ -32,8 +32,8 @@ class TestOpsWorksBase(unittest.TestCase):
opsworks.datetime, "datetime", mock.Mock(wraps=datetime.datetime)
)
mocked_datetime = self.datetime_patcher.start()
- mocked_datetime.utcnow.return_value = datetime.datetime(
- 2013, 8, 9, 23, 42
+ mocked_datetime.now.return_value = datetime.datetime(
+ 2013, 8, 9, 23, 42, tzinfo=datetime.timezone.utc
)
def tearDown(self):
diff --git a/tests/utils/botocore/__init__.py b/tests/utils/botocore/__init__.py
index bbe6a59..dddaf26 100644
--- a/tests/utils/botocore/__init__.py
+++ b/tests/utils/botocore/__init__.py
@@ -579,12 +579,12 @@ class FreezeTime(contextlib.ContextDecorator):
:param module: reference to imported module to patch (e.g. botocore.auth.datetime)
:type date: datetime.datetime
- :param date: datetime object specifying the output for utcnow()
+ :param date: datetime object specifying the output for now()
"""
def __init__(self, module, date=None):
if date is None:
- date = datetime.datetime.utcnow()
+ date = datetime.datetime.now(datetime.timezone.utc)
self.date = date
self.datetime_patcher = mock.patch.object(
module, 'datetime', mock.Mock(wraps=datetime.datetime)
@@ -592,7 +592,7 @@ class FreezeTime(contextlib.ContextDecorator):
def __enter__(self, *args, **kwargs):
mock = self.datetime_patcher.start()
- mock.utcnow.return_value = self.date
+ mock.now.return_value = self.date
def __exit__(self, *args, **kwargs):
self.datetime_patcher.stop()

View File

@ -1,139 +0,0 @@
diff --git a/awscli/arguments.py b/awscli/arguments.py
index 77639cf..3ab060b 100644
--- a/awscli/arguments.py
+++ b/awscli/arguments.py
@@ -451,7 +451,7 @@ class CLIArgument(BaseCLIArgument):
cli_name = self.cli_name
parser.add_argument(
cli_name,
- help=self.documentation,
+ help=self.documentation.replace("%", "%%"),
type=self.cli_type,
required=self.required,
)
@@ -602,7 +602,7 @@ class BooleanArgument(CLIArgument):
def add_to_parser(self, parser):
parser.add_argument(
self.cli_name,
- help=self.documentation,
+ help=self.documentation.replace("%", "%%"),
action=self._action,
default=self._default,
dest=self._destination,
diff --git a/awscli/customizations/logs/startlivetail.py b/awscli/customizations/logs/startlivetail.py
index cc5849b..bc71a3d 100644
--- a/awscli/customizations/logs/startlivetail.py
+++ b/awscli/customizations/logs/startlivetail.py
@@ -833,7 +833,7 @@ class InteractiveUI(BaseLiveTailUI):
await self._application.run_async()
def run(self):
- asyncio.get_event_loop().run_until_complete(self._run_ui())
+ asyncio.run(self._run_ui())
class PrintOnlyPrinter(BaseLiveTailPrinter):
diff --git a/awscli/customizations/wizard/app.py b/awscli/customizations/wizard/app.py
index c813b97..028fcaa 100644
--- a/awscli/customizations/wizard/app.py
+++ b/awscli/customizations/wizard/app.py
@@ -10,9 +10,9 @@
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
+import asyncio
import json
import os
-from asyncio import new_event_loop, set_event_loop
from collections.abc import MutableMapping
from prompt_toolkit.application import Application
@@ -77,14 +77,12 @@ class WizardApp(Application):
)
def run(self, pre_run=None, **kwargs):
- loop = new_event_loop()
- try:
- set_event_loop(loop)
+ def create_event_loop():
+ loop = asyncio.new_event_loop()
loop.set_exception_handler(self._handle_exception)
- f = self.run_async(pre_run=pre_run, set_exception_handler=False)
- return loop.run_until_complete(f)
- finally:
- loop.close()
+ return loop
+ f = self.run_async(pre_run=pre_run, set_exception_handler=False)
+ return asyncio.run(f, loop_factory=create_event_loop)
def _handle_exception(self, loop, context):
self.exit(exception=UnexpectedWizardException(context['exception']))
diff --git a/tests/__init__.py b/tests/__init__.py
index db70912..0ab2e4a 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -471,16 +471,9 @@ class PromptToolkitAppRunner:
# This is the function that will be passed to our thread to
# actually run the application
try:
- # When we run the app in a separate thread, there is no
- # default event loop. This ensures we create one as it is
- # likely the application will try to grab the default loop
- loop = asyncio.new_event_loop()
- asyncio.set_event_loop(loop)
app_run_context.return_value = target(*target_args)
except BaseException as e:
app_run_context.raised_exception = e
- finally:
- loop.close()
def _wait_until_app_is_done_updating(self):
self._wait_until_app_is_done_rendering()
diff --git a/tests/functional/test_utils.py b/tests/functional/test_utils.py
--- a/tests/functional/test_utils.py
+++ b/tests/functional/test_utils.py
@@ -18,7 +18,7 @@ class TestWriteException(unittest.TestCa
def test_write_exception(self):
error_message = "Some error message."
ex = Exception(error_message)
- with codecs.open(self.outfile, 'w+', encoding='utf-8') as outfile:
+ with open(self.outfile, 'w+', encoding='utf-8') as outfile:
write_exception(ex, outfile)
outfile.seek(0)
diff --git a/tests/unit/botocore/test_utils.py b/tests/unit/botocore/test_utils.py
--- a/tests/unit/botocore/test_utils.py
+++ b/tests/unit/botocore/test_utils.py
@@ -3646,20 +3646,28 @@ def test_lru_cache_weakref():
cls2 = ClassWithCachedMethod()
assert cls1.cached_fn.cache_info().currsize == 0
- assert getrefcount(cls1) == 2
- assert getrefcount(cls2) == 2
+ refcount1 = getrefcount(cls1)
+ refcount2 = getrefcount(cls2)
+ assert refcount1 in (1, 2)
+ assert refcount2 in (1, 2)
# "The count returned is generally one higher than you might expect, because
# it includes the (temporary) reference as an argument to getrefcount()."
# https://docs.python.org/3.8/library/sys.html#getrefcount
+ # However, as of 3.14: "The interpreter internally avoids some reference
+ # count modifications when loading objects onto the operands stack by
+ # borrowing references when possible. This can lead to smaller reference
+ # count values compared to previous Python versions."
+ # https://docs.python.org/3.14/whatsnew/3.14.html#whatsnew314-refcount
+
cls1.cached_fn(1, 1)
cls2.cached_fn(1, 1)
# The cache now has two entries, but the reference count remains the same as
# before.
assert cls1.cached_fn.cache_info().currsize == 2
- assert getrefcount(cls1) == 2
- assert getrefcount(cls2) == 2
+ assert getrefcount(cls1) == refcount1
+ assert getrefcount(cls2) == refcount2
# Deleting one of the objects does not interfere with the cache entries
# related to the other object.

View File

@ -1,113 +0,0 @@
diff --git a/awscli/customizations/cloudformation/yamlhelper.py b/awscli/customizations/cloudformation/yamlhelper.py
index 8e3b291..a926d53 100644
--- a/awscli/customizations/cloudformation/yamlhelper.py
+++ b/awscli/customizations/cloudformation/yamlhelper.py
@@ -91,8 +91,14 @@ def yaml_dump(dict_to_dump):
yaml.Representer = FlattenAliasRepresenter
_add_yaml_1_1_boolean_resolvers(yaml.Resolver)
yaml.Representer.add_representer(OrderedDict, _dict_representer)
+ yaml.Representer.add_representer(dict, _dict_representer)
- return dump_yaml_to_str(yaml, dict_to_dump)
+ result = dump_yaml_to_str(yaml, dict_to_dump)
+
+ # let other YAML instances use the default dict representer
+ yaml.Representer.add_representer(dict, ruamel.yaml.representer.SafeRepresenter.represent_dict)
+
+ return result
def _dict_constructor(loader, node):
diff --git a/awscli/customizations/eks/kubeconfig.py b/awscli/customizations/eks/kubeconfig.py
index 2d302d8..d00c4a8 100644
--- a/awscli/customizations/eks/kubeconfig.py
+++ b/awscli/customizations/eks/kubeconfig.py
@@ -45,7 +45,7 @@ def _get_new_kubeconfig_content():
("contexts", []),
("current-context", ""),
("kind", "Config"),
- ("preferences", OrderedDict()),
+ ("preferences", {}),
("users", []),
]
)
@@ -135,7 +135,7 @@ class KubeconfigValidator(object):
for key, value in self._validation_content.items():
if key in config.content and type(config.content[key]) == list:
for element in config.content[key]:
- if not isinstance(element, OrderedDict):
+ if not isinstance(element, dict):
raise KubeconfigCorruptedError(
f"Entry in {key} not a {dict}. "
)
diff --git a/awscli/customizations/eks/ordered_yaml.py b/awscli/customizations/eks/ordered_yaml.py
index f9b1a11..0cce12e 100644
--- a/awscli/customizations/eks/ordered_yaml.py
+++ b/awscli/customizations/eks/ordered_yaml.py
@@ -50,10 +50,18 @@ def ordered_yaml_dump(to_dump, stream=None):
:type stream: file
"""
yaml = ruamel.yaml.YAML(typ="safe", pure=True)
+ yaml.width = 99999
yaml.default_flow_style = False
yaml.Representer.add_representer(OrderedDict, _ordered_representer)
+ yaml.Representer.add_representer(dict, _ordered_representer)
if stream is None:
- return dump_yaml_to_str(yaml, to_dump)
+ result = dump_yaml_to_str(yaml, to_dump)
+ else:
+ result = None
+ yaml.dump(to_dump, stream)
- yaml.dump(to_dump, stream)
+ # let other YAML instances use the default dict representer
+ yaml.Representer.add_representer(dict, ruamel.yaml.representer.SafeRepresenter.represent_dict)
+
+ return result
diff --git a/tests/unit/customizations/cloudformation/test_yamlhelper.py b/tests/unit/customizations/cloudformation/test_yamlhelper.py
index e7ac758..b9632e9 100644
--- a/tests/unit/customizations/cloudformation/test_yamlhelper.py
+++ b/tests/unit/customizations/cloudformation/test_yamlhelper.py
@@ -130,28 +130,10 @@ class TestYaml(BaseYAMLTest):
' Name: name1\n'
)
output_dict = yaml_parse(input_template)
- expected_dict = OrderedDict(
- [
- (
- 'B_Resource',
- OrderedDict(
- [
- ('Key2', {'Name': 'name2'}),
- ('Key1', {'Name': 'name1'}),
- ]
- ),
- ),
- (
- 'A_Resource',
- OrderedDict(
- [
- ('Key2', {'Name': 'name2'}),
- ('Key1', {'Name': 'name1'}),
- ]
- ),
- ),
- ]
- )
+ expected_dict = {
+ 'B_Resource': {'Key2': {'Name': 'name2'}, 'Key1': {'Name': 'name1'}},
+ 'A_Resource': {'Key2': {'Name': 'name2'}, 'Key1': {'Name': 'name1'}}
+ }
self.assertEqual(expected_dict, output_dict)
output_template = yaml_dump(output_dict)
@@ -165,7 +147,7 @@ class TestYaml(BaseYAMLTest):
<<: *base
"""
output = yaml_parse(test_yaml)
- self.assertTrue(isinstance(output, OrderedDict))
+ self.assertTrue(isinstance(output, dict))
self.assertEqual(output.get('test').get('property'), 'value')
def test_unroll_yaml_anchors(self):

View File

@ -1 +0,0 @@
SHA512 (aws-cli-2.27.0.tar.gz) = 6651d978bfadb936ccf760603602988a70e794749d0772e7f2b2443db2381c72965d1691eedb7d082d5cd1179dc73688841ac8f0589367e2486f2b1295c59b71

View File

@ -1,16 +0,0 @@
The raw YAML output fields are sometimes printed in non-alphabetical
order, causing the raw text comparison to sometimes fail. The parsed
output is subsequently compared, and that should be all that matters.
diff --git a/tests/unit/output/test_yaml_output.py b/tests/unit/output/test_yaml_output.py
index b5e3a0a..88132f7 100644
--- a/tests/unit/output/test_yaml_output.py
+++ b/tests/unit/output/test_yaml_output.py
@@ -62,7 +62,6 @@ class TestYAMLOutput(BaseAWSCommandParamsTest):
" UserId: EXAMPLEUSERID\n"
" UserName: testuser-51\n"
)
- self.assertEqual(stdout, expected)
parsed_output = self.yaml.load(stdout)
self.assertEqual(self.parsed_response, parsed_output)

View File

@ -1,124 +0,0 @@
diff --git a/awscli/botocore/awsrequest.py b/awscli/botocore/awsrequest.py
index 4ce0449..2b14009 100644
--- a/awscli/botocore/awsrequest.py
+++ b/awscli/botocore/awsrequest.py
@@ -14,6 +14,7 @@
import functools
import io
import logging
+from collections.abc import Mapping
import socket
import sys
@@ -24,6 +25,7 @@ from botocore.compat import (
HTTPResponse,
MutableMapping,
urlencode,
+ urlparse,
urlsplit,
urlunsplit,
)
@@ -66,32 +68,34 @@ class AWSConnection:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._original_response_cls = self.response_class
- # We'd ideally hook into httplib's states, but they're all
- # __mangled_vars so we use our own state var. This variable is set
- # when we receive an early response from the server. If this value is
- # set to True, any calls to send() are noops. This value is reset to
- # false every time _send_request is called. This is to workaround the
- # fact that py2.6 (and only py2.6) has a separate send() call for the
- # body in _send_request, as opposed to endheaders(), which is where the
- # body is sent in all versions > 2.6.
+ # This variable is set when we receive an early response from the
+ # server. If this value is set to True, any calls to send() are noops.
+ # This value is reset to false every time _send_request is called.
+ # This is to workaround changes in urllib3 2.0 which uses separate
+ # send() calls in request() instead of delegating to endheaders(),
+ # which is where the body is sent in CPython's HTTPConnection.
self._response_received = False
self._expect_header_set = False
+ self._send_called = False
def close(self):
super().close()
# Reset all of our instance state we were tracking.
self._response_received = False
self._expect_header_set = False
+ self._send_called = False
self.response_class = self._original_response_cls
- def _send_request(self, method, url, body, headers, *args, **kwargs):
+ def request(self, method, url, body=None, headers=None, *args, **kwargs):
+ if headers is None:
+ headers = {}
self._response_received = False
if headers.get('Expect', b'') == b'100-continue':
self._expect_header_set = True
else:
self._expect_header_set = False
self.response_class = self._original_response_cls
- rval = super()._send_request(
+ rval = super().request(
method, url, body, headers, *args, **kwargs
)
self._expect_header_set = False
@@ -210,10 +214,13 @@ class AWSConnection:
def send(self, str):
if self._response_received:
- logger.debug(
- "send() called, but reseponse already received. "
- "Not sending data."
- )
+ if not self._send_called:
+ # urllib3 2.0 chunks and calls send potentially
+ # thousands of times inside `request` unlike the
+ # standard library. Only log this once for sanity.
+ logger.debug("send() called, but reseponse already received. "
+ "Not sending data.")
+ self._send_called = True
return
return super().send(str)
@@ -370,8 +377,14 @@ class AWSRequestPreparer:
def _prepare_url(self, original):
url = original.url
if original.params:
- params = urlencode(list(original.params.items()), doseq=True)
- url = f'{url}?{params}'
+ url_parts = urlparse(url)
+ delim = '&' if url_parts.query else '?'
+ if isinstance(original.params, Mapping):
+ params_to_encode = list(original.params.items())
+ else:
+ params_to_encode = original.params
+ params = urlencode(params_to_encode, doseq=True)
+ url = delim.join((url, params))
return url
def _prepare_headers(self, original, prepared_body=None):
diff --git a/awscli/botocore/httpsession.py b/awscli/botocore/httpsession.py
index 516bb3f..25f982d 100644
--- a/awscli/botocore/httpsession.py
+++ b/awscli/botocore/httpsession.py
@@ -328,7 +328,6 @@ class URLLib3Session:
def _get_pool_manager_kwargs(self, **extra_kwargs):
pool_manager_kwargs = {
- 'strict': True,
'timeout': self._timeout,
'maxsize': self._max_pool_connections,
'ssl_context': self._get_ssl_context(),
diff --git a/tests/unit/botocore/test_http_session.py b/tests/unit/botocore/test_http_session.py
index 90ed7d4..0a10c15 100644
--- a/tests/unit/botocore/test_http_session.py
+++ b/tests/unit/botocore/test_http_session.py
@@ -148,7 +148,6 @@ class TestURLLib3Session(unittest.TestCase):
def _assert_manager_call(self, manager, *assert_args, **assert_kwargs):
call_kwargs = {
- 'strict': True,
'maxsize': mock.ANY,
'timeout': mock.ANY,
'ssl_context': mock.ANY,