Skip to content

Commit 627e914

Browse files
Merge branch 'master' into webb/http-client-location
2 parents 2795125 + a049747 commit 627e914

35 files changed

+722
-2348
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -27,34 +27,12 @@ jobs:
2727
- uses: actions/[email protected]
2828
- uses: actions/setup-python@v6
2929
with:
30-
python-version: 3.12
30+
python-version: 3.14
3131

3232
- run: |
3333
pip install tox
3434
tox -e linters
3535
36-
check-ci-config:
37-
name: Check CI config
38-
runs-on: ubuntu-latest
39-
timeout-minutes: 10
40-
41-
steps:
42-
- uses: actions/[email protected]
43-
with:
44-
ref: ${{ github.event.pull_request.head.sha }}
45-
fetch-depth: 0
46-
- uses: actions/setup-python@v6
47-
with:
48-
python-version: 3.12
49-
50-
- name: Detect unexpected changes to tox.ini or CI
51-
run: |
52-
pip install -e .
53-
pip install -r scripts/populate_tox/requirements.txt
54-
python scripts/populate_tox/populate_tox.py --fail-on-changes
55-
pip install -r scripts/split_tox_gh_actions/requirements.txt
56-
python scripts/split_tox_gh_actions/split_tox_gh_actions.py --fail-on-changes
57-
5836
build_lambda_layer:
5937
name: Build Package
6038
runs-on: ubuntu-latest

scripts/populate_tox/README.md

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,24 @@ combination of hardcoded and generated entries.
1414

1515
The `populate_tox.py` script fills out the auto-generated part of that template.
1616
It does this by querying PyPI for each framework's package and its metadata and
17-
then determining which versions make sense to test to get good coverage.
17+
then determining which versions it makes sense to test to get good coverage.
1818

1919
By default, the lowest supported and latest version of a framework are always
2020
tested, with a number of releases in between:
2121
- If the package has majors, we pick the highest version of each major.
2222
- If the package doesn't have multiple majors, we pick two versions in between
2323
lowest and highest.
2424

25-
#### Caveats
25+
Each test suite requires at least some configuration to be added to
26+
`TEST_SUITE_CONFIG` in `scripts/populate_tox/config.py`. If you're adding a new
27+
integration, check out the [Add a new test suite](#add-a-new-test-suite) section.
2628

27-
- Make sure the integration name is the same everywhere. If it consists of
28-
multiple words, use an underscore instead of a hyphen.
29+
## Test suite config
2930

30-
## Defining constraints
31-
32-
The `TEST_SUITE_CONFIG` dictionary defines, for each integration test suite,
33-
the main package (framework, library) to test with; any additional test
34-
dependencies, optionally gated behind specific conditions; and optionally
35-
the Python versions to test on.
31+
The `TEST_SUITE_CONFIG` dictionary in `scripts/populate_tox/config.py` defines,
32+
for each integration test suite, the main package (framework, library) to test
33+
with; any additional test dependencies, optionally gated behind specific
34+
conditions; and optionally the Python versions to test on.
3635

3736
Constraints are defined using the format specified below. The following sections
3837
describe each key.
@@ -58,7 +57,7 @@ in [packaging.specifiers](https://packaging.pypa.io/en/stable/specifiers.html).
5857

5958
### `package`
6059

61-
The name of the third party package as it's listed on PyPI. The script will
60+
The name of the third-party package as it's listed on PyPI. The script will
6261
be picking different versions of this package to test.
6362

6463
This key is mandatory.
@@ -69,15 +68,15 @@ The test dependencies of the test suite. They're defined as a dictionary of
6968
`rule: [package1, package2, ...]` key-value pairs. All packages
7069
in the package list of a rule will be installed as long as the rule applies.
7170

72-
`rule`s are predefined. Each `rule` must be one of the following:
71+
Each `rule` must be one of the following:
7372
- `*`: packages will be always installed
7473
- a version specifier on the main package (e.g. `<=0.32`): packages will only
7574
be installed if the main package falls into the version bounds specified
7675
- specific Python version(s) in the form `py3.8,py3.9`: packages will only be
7776
installed if the Python version matches one from the list
7877

7978
Rules can be used to specify version bounds on older versions of the main
80-
package's dependencies, for example. If e.g. Flask tests generally need
79+
package's dependencies, for example. If Flask tests generally need
8180
Werkzeug and don't care about its version, but Flask older than 3.0 needs
8281
a specific Werkzeug version to work, you can say:
8382

@@ -176,7 +175,7 @@ be expressed like so:
176175
### `integration_name`
177176

178177
Sometimes, the name of the test suite doesn't match the name of the integration.
179-
For example, we have the `openai_base` and `openai_notiktoken` test suites, both
178+
For example, we have the `openai-base` and `openai-notiktoken` test suites, both
180179
of which are actually testing the `openai` integration. If this is the case, you
181180
can use the `integration_name` key to define the name of the integration. If not
182181
provided, it will default to the name of the test suite.
@@ -193,6 +192,11 @@ greater than 2, as the oldest and latest supported versions will always be
193192
picked. Additionally, if there is a recent prerelease, it'll also always be
194193
picked (this doesn't count towards `num_versions`).
195194

195+
For instance, `num_versions` set to `2` will only test the first supported and
196+
the last release of the package. `num_versions` equal to `3` will test the first
197+
supported, the last release, and one release in between; `num_versions` set to `4`
198+
will test an additional release in between. In all these cases, if there is
199+
a recent prerelease, it'll be picked as well in addition to the picked versions.
196200

197201
## How-Tos
198202

@@ -202,9 +206,10 @@ picked (this doesn't count towards `num_versions`).
202206
in `integrations/__init__.py`. This should be the lowest version of the
203207
framework that we can guarantee works with the SDK. If you've just added the
204208
integration, you should generally set this to the latest version of the framework
205-
at the time.
209+
at the time, unless you've verified the integration works for earlier versions
210+
as well.
206211
2. Add the integration and any constraints to `TEST_SUITE_CONFIG`. See the
207-
"Defining constraints" section for the format.
212+
[Test suite config](#test-suite-config) section for the format.
208213
3. Add the integration to one of the groups in the `GROUPS` dictionary in
209214
`scripts/split_tox_gh_actions/split_tox_gh_actions.py`.
210215
4. Run `scripts/generate-test-files.sh` and commit the changes.

scripts/populate_tox/config.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# The TEST_SUITE_CONFIG dictionary defines, for each integration test suite,
2-
# the main package (framework, library) to test with; any additional test
3-
# dependencies, optionally gated behind specific conditions; and optionally
4-
# the Python versions to test on.
2+
# at least the main package (framework, library) to test with. Additional
3+
# test dependencies, Python versions to test on, etc. can also be defined here.
54
#
65
# See scripts/populate_tox/README.md for more info on the format and examples.
76

scripts/populate_tox/populate_tox.py

Lines changed: 12 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ def _save_to_cache(package: str, version: Version, release: Optional[dict]) -> N
130130

131131

132132
def _prefilter_releases(
133-
integration: str, releases: dict[str, dict], older_than: Optional[datetime] = None
133+
integration: str,
134+
releases: dict[str, dict],
134135
) -> tuple[list[Version], Optional[Version]]:
135136
"""
136137
Filter `releases`, removing releases that are for sure unsupported.
@@ -178,9 +179,6 @@ def _prefilter_releases(
178179

179180
uploaded = datetime.fromisoformat(meta["upload_time_iso_8601"])
180181

181-
if older_than is not None and uploaded > older_than:
182-
continue
183-
184182
if CUTOFF is not None and uploaded < CUTOFF:
185183
continue
186184

@@ -224,7 +222,7 @@ def _prefilter_releases(
224222

225223

226224
def get_supported_releases(
227-
integration: str, pypi_data: dict, older_than: Optional[datetime] = None
225+
integration: str, pypi_data: dict
228226
) -> tuple[list[Version], Optional[Version]]:
229227
"""
230228
Get a list of releases that are currently supported by the SDK.
@@ -236,17 +234,15 @@ def get_supported_releases(
236234
We return the list of supported releases and optionally also the newest
237235
prerelease, if it should be tested (meaning it's for a version higher than
238236
the current stable version).
239-
240-
If an `older_than` timestamp is provided, no release newer than that will be
241-
considered.
242237
"""
243238
package = pypi_data["info"]["name"]
244239

245240
# Get a consolidated list without taking into account Python support yet
246241
# (because that might require an additional API call for some
247242
# of the releases)
248243
releases, latest_prerelease = _prefilter_releases(
249-
integration, pypi_data["releases"], older_than
244+
integration,
245+
pypi_data["releases"],
250246
)
251247

252248
def _supports_lowest(release: Version) -> bool:
@@ -665,32 +661,10 @@ def _normalize_release(release: dict) -> dict:
665661
return normalized
666662

667663

668-
def main(fail_on_changes: bool = False) -> dict[str, list]:
664+
def main() -> dict[str, list]:
669665
"""
670666
Generate tox.ini from the tox.jinja template.
671-
672-
The script has two modes of operation:
673-
- fail on changes mode (if `fail_on_changes` is True)
674-
- normal mode (if `fail_on_changes` is False)
675-
676-
Fail on changes mode is run on every PR to make sure that `tox.ini`,
677-
`tox.jinja` and this script don't go out of sync because of manual changes
678-
in one place but not the other.
679-
680-
Normal mode is meant to be run as a cron job, regenerating tox.ini and
681-
proposing the changes via a PR.
682667
"""
683-
print(f"Running in {'fail_on_changes' if fail_on_changes else 'normal'} mode.")
684-
last_updated = get_last_updated()
685-
if fail_on_changes:
686-
# We need to make the script ignore any new releases after the last updated
687-
# timestamp so that we don't fail CI on a PR just because a new package
688-
# version was released, leading to unrelated changes in tox.ini.
689-
print(
690-
f"Since we're in fail_on_changes mode, we're only considering "
691-
f"releases before the last tox.ini update at {last_updated.isoformat()}."
692-
)
693-
694668
global MIN_PYTHON_VERSION, MAX_PYTHON_VERSION
695669
meta = _fetch_sdk_metadata()
696670
sdk_python_versions = _parse_python_versions_from_classifiers(
@@ -736,12 +710,7 @@ def main(fail_on_changes: bool = False) -> dict[str, list]:
736710

737711
# Get the list of all supported releases
738712

739-
# If in fail-on-changes mode, ignore releases newer than `last_updated`
740-
older_than = last_updated if fail_on_changes else None
741-
742-
releases, latest_prerelease = get_supported_releases(
743-
integration, pypi_data, older_than
744-
)
713+
releases, latest_prerelease = get_supported_releases(integration, pypi_data)
745714

746715
if not releases:
747716
print(" Found no supported releases.")
@@ -778,9 +747,6 @@ def main(fail_on_changes: bool = False) -> dict[str, list]:
778747
}
779748
)
780749

781-
if fail_on_changes:
782-
old_file_hash = get_file_hash()
783-
784750
write_tox_file(packages)
785751

786752
# Sort the release cache file
@@ -798,36 +764,13 @@ def main(fail_on_changes: bool = False) -> dict[str, list]:
798764
):
799765
releases_cache.write(json.dumps(release) + "\n")
800766

801-
if fail_on_changes:
802-
new_file_hash = get_file_hash()
803-
if old_file_hash != new_file_hash:
804-
raise RuntimeError(
805-
dedent(
806-
"""
807-
Detected that `tox.ini` is out of sync with
808-
`scripts/populate_tox/tox.jinja` and/or
809-
`scripts/populate_tox/populate_tox.py`. This might either mean
810-
that `tox.ini` was changed manually, or the `tox.jinja`
811-
template and/or the `populate_tox.py` script were changed without
812-
regenerating `tox.ini`.
813-
814-
Please don't make manual changes to `tox.ini`. Instead, make the
815-
changes to the `tox.jinja` template and/or the `populate_tox.py`
816-
script (as applicable) and regenerate the `tox.ini` file by
817-
running scripts/generate-test-files.sh
818-
"""
819-
)
820-
)
821-
print("Done checking tox.ini. Looking good!")
822-
else:
823-
print(
824-
"Done generating tox.ini. Make sure to also update the CI YAML "
825-
"files to reflect the new test targets."
826-
)
767+
print(
768+
"Done generating tox.ini. Make sure to also update the CI YAML "
769+
"files to reflect the new test targets."
770+
)
827771

828772
return packages
829773

830774

831775
if __name__ == "__main__":
832-
fail_on_changes = len(sys.argv) == 2 and sys.argv[1] == "--fail-on-changes"
833-
main(fail_on_changes)
776+
main()

0 commit comments

Comments
 (0)