Skip to content

Commit d9c3731

Browse files
Merge branch 'release-1.40.4'
* release-1.40.4: Bumping version to 1.40.4 Update changelog based on model updates Fix installing setup dependencies for bundled installer on newer versions of pip and Python (#9420)
2 parents 44037a8 + 7825e9e commit d9c3731

File tree

10 files changed

+207
-49
lines changed

10 files changed

+207
-49
lines changed

.changes/1.40.4.json

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
[
2+
{
3+
"category": "``connectcases``",
4+
"description": "Introduces CustomEntity as part of the UserUnion data type. This field is used to indicate the entity who is performing the API action.",
5+
"type": "api-change"
6+
},
7+
{
8+
"category": "``kinesis``",
9+
"description": "Amazon KDS now supports tagging and attribute-based access control (ABAC) for enhanced fan-out consumers.",
10+
"type": "api-change"
11+
},
12+
{
13+
"category": "``pinpoint-sms-voice-v2``",
14+
"description": "AWS End User Messaging has added MONITOR and FILTER functionality to SMS Protect.",
15+
"type": "api-change"
16+
},
17+
{
18+
"category": "``qbusiness``",
19+
"description": "Add support for anonymous user access for Q Business applications",
20+
"type": "api-change"
21+
},
22+
{
23+
"category": "``sagemaker``",
24+
"description": "Introduced support for P5en instance types on SageMaker Studio for JupyterLab and CodeEditor applications.",
25+
"type": "api-change"
26+
},
27+
{
28+
"category": "``sagemaker-metrics``",
29+
"description": "SageMaker Metrics Service now supports FIPS endpoint in all US and Canada Commercial regions.",
30+
"type": "api-change"
31+
},
32+
{
33+
"category": "``ssm``",
34+
"description": "This release adds support for just-In-time node access in AWS Systems Manager. Just-in-time node access enables customers to move towards zero standing privileges by requiring operators to request access and obtain approval before remotely connecting to nodes managed by the SSM Agent.",
35+
"type": "api-change"
36+
},
37+
{
38+
"category": "``ssm-guiconnect``",
39+
"description": "This release adds API support for the connection recording GUI Connect feature of AWS Systems Manager",
40+
"type": "api-change"
41+
},
42+
{
43+
"category": "bundled-installer",
44+
"description": "Fix installing setup dependencies on newer versions of pip",
45+
"type": "bugfix"
46+
}
47+
]

.github/workflows/run-bundle-test.yml

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Run bundle test
2+
3+
on:
4+
push:
5+
pull_request:
6+
branches-ignore: [ master ]
7+
8+
jobs:
9+
test-bundle:
10+
runs-on: ${{ matrix.os }}
11+
strategy:
12+
fail-fast: false
13+
matrix:
14+
python-version: ["3.9", "3.10", "3.11", "3.12"]
15+
os: [ubuntu-latest, macOS-latest]
16+
steps:
17+
- uses: actions/checkout@v4
18+
- name: Set up Python ${{ matrix.python-version }}
19+
uses: actions/setup-python@v5
20+
with:
21+
python-version: ${{ matrix.python-version }}
22+
- name: Install dependencies
23+
run: python scripts/ci/install
24+
- name: Install additional dependencies
25+
run: pip install virtualenv==16.3.0 setuptools-scm==3.3.3 # same as internal generate-bundle.ts
26+
- name: Test the bundle
27+
run: python scripts/ci/test-bundle

CHANGELOG.rst

+14
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@
22
CHANGELOG
33
=========
44

5+
1.40.4
6+
======
7+
8+
* api-change:``connectcases``: Introduces CustomEntity as part of the UserUnion data type. This field is used to indicate the entity who is performing the API action.
9+
* api-change:``kinesis``: Amazon KDS now supports tagging and attribute-based access control (ABAC) for enhanced fan-out consumers.
10+
* api-change:``pinpoint-sms-voice-v2``: AWS End User Messaging has added MONITOR and FILTER functionality to SMS Protect.
11+
* api-change:``qbusiness``: Add support for anonymous user access for Q Business applications
12+
* api-change:``sagemaker``: Introduced support for P5en instance types on SageMaker Studio for JupyterLab and CodeEditor applications.
13+
* api-change:``sagemaker-metrics``: SageMaker Metrics Service now supports FIPS endpoint in all US and Canada Commercial regions.
14+
* api-change:``ssm``: This release adds support for just-In-time node access in AWS Systems Manager. Just-in-time node access enables customers to move towards zero standing privileges by requiring operators to request access and obtain approval before remotely connecting to nodes managed by the SSM Agent.
15+
* api-change:``ssm-guiconnect``: This release adds API support for the connection recording GUI Connect feature of AWS Systems Manager
16+
* bugfix:bundled-installer: Fix installing setup dependencies on newer versions of pip
17+
18+
519
1.40.3
620
======
721

awscli/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import os
2020

21-
__version__ = '1.40.3'
21+
__version__ = '1.40.4'
2222

2323
#
2424
# Get our data path to be added to botocore's search path

doc/source/conf.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
# The short X.Y version.
5353
version = '1.40'
5454
# The full version, including alpha/beta/rc tags.
55-
release = '1.40.3'
55+
release = '1.40.4'
5656

5757
# The language for content autogenerated by Sphinx. Refer to documentation
5858
# for a list of supported languages.

scripts/ci/test-bundle

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#!/usr/bin/env python
2+
# Don't run tests from the root repo dir.
3+
# We want to ensure we're importing from the installed
4+
# binary package not from the CWD.
5+
6+
import os
7+
import re
8+
from subprocess import check_output
9+
from awscli.testutils import cd
10+
11+
_dname = os.path.dirname
12+
13+
REPO_ROOT = _dname(_dname(_dname(os.path.abspath(__file__))))
14+
15+
16+
def run(command):
17+
print(f'Running {command}')
18+
return check_output(command, shell=True)
19+
20+
21+
def run_make_bundle():
22+
"""
23+
Builds the bundled installer, and returns its path
24+
"""
25+
output = run(f'{REPO_ROOT}/scripts/make-bundle')
26+
match = re.search(
27+
r'Zipped bundle installer is at: (.+?\.zip)', output.decode('utf-8')
28+
)
29+
if not match:
30+
raise RuntimeError("Could not find bundle path in make-bundle output")
31+
32+
return match.group(1)
33+
34+
35+
def install_from_bundle(zip_path):
36+
run(f'unzip -o {bundle_path}')
37+
path_without_zip = bundle_path[:-4]
38+
run(
39+
f'sudo {path_without_zip}/install -i /usr/local/aws -b /usr/local/bin/aws'
40+
)
41+
42+
43+
def verify_installation():
44+
version_output = run("aws --version")
45+
print(f"Installed AWS CLI version: {version_output}")
46+
47+
48+
if __name__ == "__main__":
49+
with cd(os.path.join(REPO_ROOT)):
50+
bundle_path = run_make_bundle()
51+
install_from_bundle(bundle_path)
52+
verify_installation()

scripts/install

+12-19
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ def pip_install_packages(install_dir):
150150

151151
with cd(PACKAGES_DIR):
152152
run(
153-
'{} -m pip install {} --find-links file://{} {}'.format(
153+
'{} -m pip install {} --find-links {} {}'.format(
154154
python, INSTALL_ARGS, PACKAGES_DIR, cli_tarball
155155
)
156156
)
@@ -160,24 +160,17 @@ def _install_setup_deps(python, setup_package_dir):
160160
# Some packages declare `setup_requires`, which is a list of dependencies
161161
# to be used at setup time. These need to be installed before anything
162162
# else, and pip doesn't manage them. We have to manage this ourselves
163-
# so for now we're explicitly installing the one setup_requires package
164-
# we need. This comes from python-dateutils.
165-
setuptools_scm_tarball = _get_package_tarball(
166-
setup_package_dir, 'setuptools_scm'
167-
)
168-
run(
169-
(
170-
'{} -m pip install --no-binary :all: --no-cache-dir --no-index '
171-
'--find-links file://{} {}'
172-
).format(python, setup_package_dir, setuptools_scm_tarball)
173-
)
174-
wheel_tarball = _get_package_tarball(setup_package_dir, 'wheel')
175-
run(
176-
(
177-
'{} -m pip install --no-binary :all: --no-cache-dir --no-index '
178-
'--find-links file://{} {}'
179-
).format(python, setup_package_dir, wheel_tarball)
180-
)
163+
# so for now we're explicitly installing setuptools_scm which is needed for
164+
# python-dateutils. We're also now installing setuptools since its no
165+
# longer installed alongside pip for 3.12+.
166+
for package in ['setuptools-', 'wheel', 'setuptools_scm']:
167+
# these are actually wheels, but the bundle lookup logic is the same
168+
tarball = _get_package_tarball(setup_package_dir, package)
169+
run(
170+
'{} -m pip install {} --find-links {} {}'.format(
171+
python, INSTALL_ARGS, PACKAGES_DIR, tarball
172+
)
173+
)
181174

182175

183176
def create_symlink(real_location, symlink_name):

scripts/make-bundle

+51-26
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ interface for those not familiar with the python
1212
ecosystem.
1313
1414
"""
15+
1516
import os
1617
import sys
1718
import subprocess
@@ -31,10 +32,13 @@ PINNED_RUNTIME_DEPS = [
3132
# require extra build time dependencies. We are pinning it to
3233
# a version that does not need those.
3334
('colorama', '0.4.5'),
35+
# 2.0.0 of urllib3 started requiring hatchling as well
36+
('urllib3', '1.26.20'),
3437
]
3538
BUILDTIME_DEPS = [
39+
('setuptools', '75.4.0'), # start of >= 3.9
3640
('setuptools-scm', '3.3.3'),
37-
('wheel', '0.33.6'),
41+
('wheel', '0.45.1'), # 0.46.0+ requires packaging
3842
]
3943
PIP_DOWNLOAD_ARGS = '--no-build-isolation --no-binary :all:'
4044

@@ -54,14 +58,14 @@ def cd(dirname):
5458

5559

5660
def run(cmd):
57-
sys.stdout.write("Running cmd: %s\n" % cmd)
58-
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
59-
stderr=subprocess.PIPE)
61+
sys.stdout.write(f"Running cmd: {cmd}\n")
62+
p = subprocess.Popen(
63+
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
64+
)
6065
stdout, stderr = p.communicate()
6166
rc = p.wait()
6267
if p.returncode != 0:
63-
raise BadRCError("Bad rc (%s) for cmd '%s': %s" % (
64-
rc, cmd, stderr + stdout))
68+
raise BadRCError(f"Bad rc ({rc}) for cmd '{cmd}': {stderr + stdout}")
6569
return stdout
6670

6771

@@ -79,17 +83,33 @@ def create_scratch_dir():
7983
def download_package_tarballs(dirname, packages):
8084
with cd(dirname):
8185
for package, package_version in packages:
82-
run('%s -m pip download %s==%s %s' % (
83-
sys.executable, package, package_version, PIP_DOWNLOAD_ARGS
84-
))
86+
run(
87+
f'{sys.executable} -m pip download {package}=={package_version}'
88+
f' {PIP_DOWNLOAD_ARGS}'
89+
)
90+
91+
92+
def download_package_wheels(dirname, packages):
93+
with cd(dirname):
94+
for package, package_version in packages:
95+
run(
96+
f'{sys.executable} -m pip download {package}=={package_version}'
97+
f' --only-binary :all:'
98+
)
99+
100+
101+
def validate_that_wheels_are_universal(dirname):
102+
with cd(dirname):
103+
for wheel_path in os.listdir():
104+
if not wheel_path.endswith('py3-none-any.whl'):
105+
raise ValueError(f'Found a non universal wheel: {wheel_path}')
85106

86107

87108
def download_cli_deps(scratch_dir, packages):
88109
# pip download will always download a more recent version of a package
89110
# even if one exists locally. The list of packages supplied in `packages`
90111
# forces the use of a specific runtime dependency.
91-
awscli_dir = os.path.dirname(
92-
os.path.dirname(os.path.abspath(__file__)))
112+
awscli_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
93113
pinned_packages = " ".join(
94114
f"{name}=={version}" for (name, version) in packages
95115
)
@@ -104,20 +124,21 @@ def _remove_cli_zip(scratch_dir):
104124

105125

106126
def add_cli_sdist(scratch_dir):
107-
awscli_dir = os.path.dirname(
108-
os.path.dirname(os.path.abspath(__file__)))
127+
awscli_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
109128
if os.path.exists(os.path.join(awscli_dir, 'dist')):
110129
shutil.rmtree(os.path.join(awscli_dir, 'dist'))
111130
with cd(awscli_dir):
112-
run('%s setup.py sdist' % sys.executable)
131+
run(f'{sys.executable} setup.py sdist')
113132
filename = os.listdir('dist')[0]
114-
shutil.move(os.path.join('dist', filename),
115-
os.path.join(scratch_dir, filename))
133+
shutil.move(
134+
os.path.join('dist', filename), os.path.join(scratch_dir, filename)
135+
)
116136

117137

118138
def create_bootstrap_script(scratch_dir):
119139
install_script = os.path.join(
120-
os.path.dirname(os.path.abspath(__file__)), 'install')
140+
os.path.dirname(os.path.abspath(__file__)), 'install'
141+
)
121142
shutil.copy(install_script, os.path.join(scratch_dir, 'install'))
122143

123144

@@ -139,11 +160,11 @@ def zip_dir(scratch_dir):
139160
def verify_preconditions():
140161
# The pip version looks like:
141162
# 'pip 1.4.1 from ....'
142-
pip_version = run(
143-
'%s -m pip --version' % sys.executable).strip().split()[1]
163+
pip_version = run(f'{sys.executable} -m pip --version').strip().split()[1]
144164
# Virtualenv version just has the version string: '1.14.5\n'
145165
virtualenv_version = run(
146-
'%s -m virtualenv --version' % sys.executable).strip()
166+
f'{sys.executable} -m virtualenv --version'
167+
).strip()
147168
_min_version_required('9.0.1', pip_version, 'pip')
148169
_min_version_required('15.1.0', virtualenv_version, 'virtualenv')
149170

@@ -156,15 +177,17 @@ def _min_version_required(min_version, actual_version, name):
156177
for min_version_part, actual_version_part in zip(min_split, actual_split):
157178
if int(actual_version_part) >= int(min_version_part):
158179
return
159-
raise ValueError("%s requires at least version %s, but version %s was "
160-
"found." % (name, min_version, actual_version))
180+
raise ValueError(
181+
f'{name} requires at least version {min_version}, '
182+
f'but version {actual_version} was found.'
183+
)
161184

162185

163186
def main():
164187
verify_preconditions()
165188
scratch_dir = create_scratch_dir()
166189
package_dir = os.path.join(scratch_dir, 'packages')
167-
print("Bundle dir at: %s" % scratch_dir)
190+
print(f"Bundle dir at: {scratch_dir}")
168191
download_package_tarballs(
169192
package_dir,
170193
packages=EXTRA_RUNTIME_DEPS,
@@ -174,17 +197,19 @@ def main():
174197
# manually install them. We isolate them to a particular directory so we
175198
# can run the install before the things they're dependent on. We have to do
176199
# this because pip won't actually find them since it doesn't handle build
177-
# dependencies.
200+
# dependencies. We use wheels for this, to avoid bootstrapping setuptools
201+
# in 3.12+ where it's no longer included by default.
178202
setup_dir = os.path.join(package_dir, 'setup')
179-
download_package_tarballs(
203+
download_package_wheels(
180204
setup_dir,
181205
packages=BUILDTIME_DEPS,
182206
)
207+
validate_that_wheels_are_universal(setup_dir)
183208
download_cli_deps(package_dir, packages=PINNED_RUNTIME_DEPS)
184209
add_cli_sdist(package_dir)
185210
create_bootstrap_script(scratch_dir)
186211
zip_filename = zip_dir(scratch_dir)
187-
print("Zipped bundle installer is at: %s" % zip_filename)
212+
print(f"Zipped bundle installer is at: {zip_filename}")
188213

189214

190215
if __name__ == '__main__':

setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ universal = 0
33

44
[metadata]
55
requires_dist =
6-
botocore==1.38.4
6+
botocore==1.38.5
77
docutils>=0.18.1,<=0.19
88
s3transfer>=0.12.0,<0.13.0
99
PyYAML>=3.10,<6.1

0 commit comments

Comments
 (0)