Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"type": "feature",
"category": "Python",
"description": "Add support for Python 3.14 ([#2163](https://github.com/aws/chalice/pull/2163))"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"type": "enhancement",
"category": "Pip",
"description": "Update pip to the latest version (<26.2) ([#2163](https://github.com/aws/chalice/pull/2163))"
}
10 changes: 5 additions & 5 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
python-version: ['3.10', 3.11, 3.12, 3.13]
python-version: ['3.10', 3.11, 3.12, 3.13, 3.14]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- uses: actions/setup-python@v6
name: Set up Python ${{ matrix.python-version }}
with:
python-version: ${{ matrix.python-version }}
Expand All @@ -33,13 +33,13 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10', 3.11, 3.12, 3.13]
python-version: ['3.10', 3.11, 3.12, 3.13, 3.14]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v6
with:
node-version: '24'
- uses: actions/setup-python@v2
- uses: actions/setup-python@v6
name: Set up Python ${{ matrix.python-version }}
with:
python-version: ${{ matrix.python-version }}
Expand All @@ -66,7 +66,7 @@ jobs:
# python-version: [3.6, 3.7, 3.8, 3.9]
# steps:
# - uses: actions/checkout@v2
# - uses: actions/setup-python@v2
# - uses: actions/setup-python@v6
# name: Set up Python ${{ matrix.python-version }}
# with:
# python-version: ${{ matrix.python-version }}
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ First, create a virtual environment for chalice::
$ source venv/bin/activate

Keep in mind that chalice is designed to work with AWS Lambda.
Make sure to create your virtual environment using Python 3.10 to 3.13,
Make sure to create your virtual environment using Python 3.10 to 3.14,
as these are versions currently supported by both AWS Lambda and chalice.

Next, you'll need to install chalice. The easiest way to configure this
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ Quickstart
In this tutorial, you'll use the ``chalice`` command line utility
to create and deploy a basic REST API. This quickstart uses Python 3.10,
but AWS Chalice supports all versions of python supported by AWS Lambda,
which includes Python 3.10 through python 3.13.
which includes Python 3.10 through python 3.14.

To install Chalice, we'll first create and activate a virtual environment
in python3.10::
Expand Down
17 changes: 13 additions & 4 deletions chalice/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,13 @@ def __init__(self, value):
self.value = value


def get_string_literal_value(node):
# type: (ast.AST) -> Optional[str]
if isinstance(node, ast.Constant) and isinstance(node.value, str):
return node.value
return None


class ParsedCode(object):
def __init__(self, parsed_ast, symbol_table):
# type: (ast.AST, ChainedSymbolTable) -> None
Expand Down Expand Up @@ -411,8 +418,9 @@ def visit_Assign(self, node):
rhs_inferred_type = self._get_inferred_type_for_node(node.value)
if rhs_inferred_type is None:
# Special casing assignment to a string literal.
if isinstance(node.value, ast.Str):
rhs_inferred_type = StringLiteral(node.value.s)
string_value = get_string_literal_value(node.value)
if string_value is not None:
rhs_inferred_type = StringLiteral(string_value)
self._set_inferred_type_for_node(node.value, rhs_inferred_type)
for t in node.targets:
if isinstance(t, ast.Name):
Expand Down Expand Up @@ -451,9 +459,10 @@ def visit_Call(self, node):
# e_0(e_1) : B3CT[e_1]
if len(node.args) >= 1:
service_arg = node.args[0]
if isinstance(service_arg, ast.Str):
service_name = get_string_literal_value(service_arg)
if service_name is not None:
self._set_inferred_type_for_node(
node, Boto3ClientType(service_arg.s))
node, Boto3ClientType(service_name))
elif isinstance(self._get_inferred_type_for_node(service_arg),
StringLiteral):
sub_type = self._get_inferred_type_for_node(service_arg)
Expand Down
4 changes: 2 additions & 2 deletions chalice/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,11 @@ def lambda_python_version(self) -> str:
major, minor = sys.version_info[0], sys.version_info[1]
if (major, minor) < (3, 10):
return 'python3.10'
elif (major, minor) <= (3, 12):
elif (major, minor) <= (3, 13):
# Otherwise we use your current version of python if Lambda
# supports it.
return f'python{major}.{minor}'
return 'python3.13'
return 'python3.14'

@property
def log_retention_in_days(self) -> int:
Expand Down
52 changes: 37 additions & 15 deletions chalice/deploy/packager.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ class BaseLambdaDeploymentPackager(object):
'python3.11': 'cp311',
'python3.12': 'cp312',
'python3.13': 'cp313',
'python3.14': 'cp314',
}

def __init__(
Expand Down Expand Up @@ -499,6 +500,7 @@ class DependencyBuilder(object):
'cp311': (2, 26),
'cp312': (2, 34),
'cp313': (2, 34),
'cp314': (2, 34),
}
# Fallback version if we're on an unknown python version
# not in _RUNTIME_GLIBC.
Expand Down Expand Up @@ -635,9 +637,27 @@ def _download_binary_wheels(
# Try to get binary wheels for each package that isn't compatible.
logger.debug("Downloading manylinux wheels: %s", packages)
self._pip.download_manylinux_wheels(
abi, [pkg.identifier for pkg in packages], directory
abi,
[pkg.identifier for pkg in packages],
directory,
self._get_pip_platforms(abi),
)

def _get_pip_platforms(self, abi: str) -> List[str]:
# Pip treats --platform as a literal tag and does not auto-include
# lower manylinux_X_Y versions, so we enumerate every glibc minor up
# to the runtime's. The trailing manylinux2014_x86_64 alias engages
# pip's legacy compatibility hierarchy (manylinux1, manylinux2010).
runtime_major, runtime_minor = self._RUNTIME_GLIBC.get(
abi, self._DEFAULT_GLIBC
)
platforms = [
'manylinux_%s_%s_x86_64' % (runtime_major, minor)
for minor in range(17, runtime_minor + 1)
]
platforms.append('manylinux2014_x86_64')
return platforms

def _download_sdists(self, packages: Set[Package], directory: str) -> None:
logger.debug("Downloading missing sdists: %s", packages)
self._pip.download_sdists(
Expand Down Expand Up @@ -1161,31 +1181,33 @@ def download_all_dependencies(
self.build_wheel(wheel_package_path, directory)

def download_manylinux_wheels(
self, abi: str, packages: List[str], directory: str
self,
abi: str,
packages: List[str],
directory: str,
platforms: Optional[List[str]] = None,
) -> None:
"""Download wheel files for manylinux for all the given packages."""
# If any one of these dependencies fails pip will bail out. Since we
# are only interested in all the ones we can download, we need to feed
# each package to pip individually. The return code of pip doesn't
# matter here since we will inspect the working directory to see which
# wheels were downloaded. We are only interested in wheel files
# compatible with lambda, which means manylinux1_x86_64 platform and
# compatible with lambda, which means a manylinux x86_64 platform and
# cpython implementation. The compatible abi depends on the python
# version and is checked later.
if platforms is None:
platforms = ['manylinux2014_x86_64']
for package in packages:
arguments = [
'--only-binary=:all:',
'--no-deps',
'--platform',
'manylinux2014_x86_64',
'--implementation',
'cp',
'--abi',
abi,
'--dest',
directory,
arguments = ['--only-binary=:all:', '--no-deps']
for platform in platforms:
arguments.extend(['--platform', platform])
arguments.extend([
'--implementation', 'cp',
'--abi', abi,
'--dest', directory,
package,
]
])
self._execute('download', arguments)

def download_sdists(self, packages: List[str], directory: str) -> None:
Expand Down
4 changes: 3 additions & 1 deletion chalice/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,9 @@ class CreatePipelineTemplateV2(BasePipelineTemplate):
"Description": "Enter the name of your application"
},
"CodeBuildImage": {
"Default": "aws/codebuild/amazonlinux2-x86_64-standard:3.0",
"Default": (
"aws/codebuild/amazonlinux2023-x86_64-standard:5.0"
),
"Type": "String",
"Description": "Name of codebuild image to use."
}
Expand Down
2 changes: 1 addition & 1 deletion docs/source/topics/cd.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ version, ``v2``, is recommended. The version can be specified using the
* The ``v2`` buildspec uses `runtime-versions <https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html#build-spec.phases.install.runtime-versions>`__
to configure which version of Python to use instead of a Python
version specific CodeBuild image. For ``v2`` templates the
``aws/codebuild/amazonlinux2-x86_64-standard`` image.
``aws/codebuild/amazonlinux2023-x86_64-standard`` image.

**The v2 pipeline template requires Python 3.10 or higher.** If you're using
Python versions less than 3.10 you must use the ``v1`` pipeline template.
Expand Down
10 changes: 5 additions & 5 deletions docs/source/topics/pyversion.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Python Version Support
======================

Chalice supports Python 3.10 through Python 3.13. You can see the list of
Chalice supports Python 3.10 through Python 3.14. You can see the list of
supported python versions for Lambda in their
`docs <https://docs.aws.amazon.com/lambda/latest/dg/lambda-python.html>`__.

Expand Down Expand Up @@ -35,8 +35,8 @@ explicitly configure which version of python you want to use. For example::


In the example above, we're using python 3.10.20 so chalice automatically
selects the ``python3.10`` runtime for lambda. If we were using python 3.13,
chalice would automatically select ``python3.13`` as the runtime.
selects the ``python3.10`` runtime for lambda. If we were using python 3.14,
chalice would automatically select ``python3.14`` as the runtime.

Chalice will emit a warning if the minor version does not match a python
version supported by Lambda. Chalice will select the closest Lambda version
Expand All @@ -61,7 +61,7 @@ Python 3.10 ::
...
https://endpoint/api

To upgrade the application to use Python 3.13, create a python3 virtual
To upgrade the application to use Python 3.14, create a python3 virtual
environment and redeploy.

::
Expand All @@ -70,6 +70,6 @@ environment and redeploy.
$ python3 -m venv /tmp/venv3
$ source /tmp/venv3/bin/activate
$ python --version
Python 3.13.3
Python 3.14.4
$ chalice deploy
...
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def recursive_include(relative_dir):
'click>=7,<9.0',
'botocore>=1.14.0,<2.0.0',
'six>=1.10.0,<2.0.0',
'pip>=9,<25.1',
'pip>=9,<26.2',
'jmespath>=0.9.3,<2.0.0',
'pyyaml>=5.3.1,<7.0.0',
'inquirer>=3.0.0,<4.0.0',
Expand Down Expand Up @@ -73,5 +73,6 @@ def recursive_include(relative_dir):
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: 3.13',
'Programming Language :: Python :: 3.14',
],
)
4 changes: 2 additions & 2 deletions tests/functional/cli/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,8 +410,8 @@ def test_error_when_no_deployed_record(runner, mock_cli_factory):


@pytest.mark.skipif(
(3, 10) <= sys.version_info[:2] <= (3, 13),
reason=("Cannot generate pipeline for python3.10 - python3.13"),
(3, 10) <= sys.version_info[:2] <= (3, 14),
reason=("Cannot generate pipeline for python3.10 - python3.14"),
)
def test_can_generate_pipeline_for_all(runner):
with runner.isolated_filesystem():
Expand Down
4 changes: 4 additions & 0 deletions tests/functional/test_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ def test_can_get_sdist_if_missing_initially(self, tmpdir, pip_runner):
pip.packages_to_download(
expected_args=[
'--only-binary=:all:', '--no-deps', '--platform',
'manylinux_2_17_x86_64', '--platform',
'manylinux2014_x86_64', '--implementation', 'cp',
'--abi', 'cp36m', '--dest', mock.ANY,
'foo==1.2'
Expand Down Expand Up @@ -743,6 +744,7 @@ def test_can_replace_incompat_whl(self, tmpdir, osutils, pip_runner):
pip.packages_to_download(
expected_args=[
'--only-binary=:all:', '--no-deps', '--platform',
'manylinux_2_17_x86_64', '--platform',
'manylinux2014_x86_64', '--implementation', 'cp',
'--abi', 'cp36m', '--dest', mock.ANY,
'bar==1.2'
Expand Down Expand Up @@ -785,6 +787,7 @@ def test_whitelist_sqlalchemy(self, tmpdir, osutils, pip_runner,
pip.packages_to_download(
expected_args=[
'--only-binary=:all:', '--no-deps', '--platform',
'manylinux_2_17_x86_64', '--platform',
'manylinux2014_x86_64', '--implementation', 'cp',
'--abi', abi, '--dest', mock.ANY,
'%s==1.1.18' % package
Expand Down Expand Up @@ -942,6 +945,7 @@ def test_build_into_existing_dir_with_preinstalled_packages(
pip.packages_to_download(
expected_args=[
'--only-binary=:all:', '--no-deps', '--platform',
'manylinux_2_17_x86_64', '--platform',
'manylinux2014_x86_64', '--implementation', 'cp',
'--abi', abi, '--dest', mock.ANY,
'foo==1.2'
Expand Down
Loading
Loading