diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index cb604e08a7e..fdf14d7e55d 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -93,7 +93,7 @@ jobs: needs: - release_info runs-on: - - ubuntu-20.04 + - ubuntu-22.04 steps: - name: Check out code uses: actions/checkout@v3 diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 8290e886716..99cdb1f04ea 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -112,7 +112,7 @@ jobs: needs: - classify_changes runs-on: - - ubuntu-20.04 + - ubuntu-22.04 steps: - name: Check out code uses: actions/checkout@v4 @@ -373,7 +373,7 @@ jobs: needs: - classify_changes runs-on: - - ubuntu-20.04 + - ubuntu-22.04 steps: - name: Check out code uses: actions/checkout@v3 @@ -563,7 +563,7 @@ jobs: if: github.repository_owner == 'pantsbuild' name: Ensure PR has a category label runs-on: - - ubuntu-20.04 + - ubuntu-22.04 steps: - env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -581,7 +581,7 @@ jobs: needs: - classify_changes runs-on: - - ubuntu-20.04 + - ubuntu-22.04 steps: - env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -608,7 +608,7 @@ jobs: release: ${{ steps.classify.outputs.release }} rust: ${{ steps.classify.outputs.rust }} runs-on: - - ubuntu-20.04 + - ubuntu-22.04 steps: - name: Check out code uses: actions/checkout@v4 @@ -630,7 +630,7 @@ jobs: - bootstrap_pants_linux_x86_64 - classify_changes runs-on: - - ubuntu-20.04 + - ubuntu-22.04 steps: - name: Check out code uses: actions/checkout@v4 @@ -684,7 +684,7 @@ jobs: needs: - set_merge_ok runs-on: - - ubuntu-20.04 + - ubuntu-22.04 steps: - run: "merge_ok=\"${{ needs.set_merge_ok.outputs.merge_ok }}\"\nif [[ \"${merge_ok}\" == \"true\" ]]; then\n echo\ \ \"Merge OK\"\n exit 0\nelse\n echo \"Merge NOT OK\"\n exit 1\nfi\n" @@ -721,7 +721,7 @@ jobs: outputs: merge_ok: ${{ steps.set_merge_ok.outputs.merge_ok }} runs-on: - - ubuntu-20.04 + - ubuntu-22.04 steps: - id: set_merge_ok run: echo 'merge_ok=true' >> ${GITHUB_OUTPUT} @@ -790,7 +790,7 @@ jobs: - bootstrap_pants_linux_x86_64 - classify_changes runs-on: - - ubuntu-20.04 + - ubuntu-22.04 steps: - name: Check out code uses: actions/checkout@v4 @@ -882,7 +882,7 @@ jobs: - bootstrap_pants_linux_x86_64 - classify_changes runs-on: - - ubuntu-20.04 + - ubuntu-22.04 steps: - name: Check out code uses: actions/checkout@v4 @@ -974,7 +974,7 @@ jobs: - bootstrap_pants_linux_x86_64 - classify_changes runs-on: - - ubuntu-20.04 + - ubuntu-22.04 steps: - name: Check out code uses: actions/checkout@v4 @@ -1066,7 +1066,7 @@ jobs: - bootstrap_pants_linux_x86_64 - classify_changes runs-on: - - ubuntu-20.04 + - ubuntu-22.04 steps: - name: Check out code uses: actions/checkout@v4 @@ -1158,7 +1158,7 @@ jobs: - bootstrap_pants_linux_x86_64 - classify_changes runs-on: - - ubuntu-20.04 + - ubuntu-22.04 steps: - name: Check out code uses: actions/checkout@v4 @@ -1250,7 +1250,7 @@ jobs: - bootstrap_pants_linux_x86_64 - classify_changes runs-on: - - ubuntu-20.04 + - ubuntu-22.04 steps: - name: Check out code uses: actions/checkout@v4 @@ -1342,7 +1342,7 @@ jobs: - bootstrap_pants_linux_x86_64 - classify_changes runs-on: - - ubuntu-20.04 + - ubuntu-22.04 steps: - name: Check out code uses: actions/checkout@v4 @@ -1434,7 +1434,7 @@ jobs: - bootstrap_pants_linux_x86_64 - classify_changes runs-on: - - ubuntu-20.04 + - ubuntu-22.04 steps: - name: Check out code uses: actions/checkout@v4 @@ -1526,7 +1526,7 @@ jobs: - bootstrap_pants_linux_x86_64 - classify_changes runs-on: - - ubuntu-20.04 + - ubuntu-22.04 steps: - name: Check out code uses: actions/checkout@v4 @@ -1618,7 +1618,7 @@ jobs: - bootstrap_pants_linux_x86_64 - classify_changes runs-on: - - ubuntu-20.04 + - ubuntu-22.04 steps: - name: Check out code uses: actions/checkout@v4 diff --git a/docs/notes/2.24.x.md b/docs/notes/2.24.x.md index 36621f66191..755ac7b3ef9 100644 --- a/docs/notes/2.24.x.md +++ b/docs/notes/2.24.x.md @@ -16,6 +16,7 @@ We offer [formal sponsorship tiers for companies](https://www.pantsbuild.org/spo ### Deprecations +- **Python 2.7**: As announced in the v2.23.x release series, Pants v2.24 and later are not proactively tested in CI with Python 2.7 since [Python 2.7 is no longer supported by its maintainers as of 1 January 2020](https://www.python.org/doc/sunset-python-2/). While Pants may continue to work with Python 2.7 in the near term, Pants no longer officially supports use of Python 2.7, and, consequently, any remaining support for Python 2.7 may "bit rot" and diverge over time. Contributions to fix issues with Python 2.7 support will continue to be accepted, but will depend on any community contributions and will not consitute continued official support for Python 2.7. ### General @@ -26,7 +27,11 @@ We offer [formal sponsorship tiers for companies](https://www.pantsbuild.org/spo #### Python -The default lockfiles bundled with Pants for various tools (ex: to run `black`) no longer support Python 3.7. The minimum Python version is now 3.8. Pants still supports running Python 3.7 (and earlier!) user code, but you will need to [generate your own lockfiles](https://www.pantsbuild.org/stable/docs/python/overview/lockfiles#lockfiles-for-tools). See the announcement at for further context. +Deprecations: + +- Pants v2.24 and later are not proactively tested in CI with Python 2.7 since [Python 2.7 is no longer supported by its maintainers as of 1 January 2020](https://www.python.org/doc/sunset-python-2/). While Pants may continue to work with Python 2.7 in the near term, Pants no longer officially supports use of Python 2.7, and, consequently, any remaining support for Python 2.7 may "bit rot" and diverge over time. Contributions to fix issues with Python 2.7 support will continue to be accepted, but will depend on any community contributions and will not constitute continued official support for Python 2.7. + +- The default lockfiles bundled with Pants for various tools (ex: to run `black`) no longer support Python 3.7. The minimum Python version is now 3.8. Pants still supports running Python 3.7 (and earlier!) user code, but you will need to [generate your own lockfiles](https://www.pantsbuild.org/stable/docs/python/overview/lockfiles#lockfiles-for-tools). See the announcement at for further context. As a consequence of the lockfile generation, newer versions of many tools are now included in the default lockfiles. diff --git a/src/python/pants/backend/python/dependency_inference/parse_python_dependencies_test.py b/src/python/pants/backend/python/dependency_inference/parse_python_dependencies_test.py index a305b1caa83..56b24e97fdc 100644 --- a/src/python/pants/backend/python/dependency_inference/parse_python_dependencies_test.py +++ b/src/python/pants/backend/python/dependency_inference/parse_python_dependencies_test.py @@ -23,7 +23,6 @@ from pants.core.util_rules import stripped_source_files from pants.engine.addresses import Address from pants.testutil.python_interpreter_selection import ( - skip_unless_python27_present, skip_unless_python38_present, skip_unless_python39_present, ) @@ -439,52 +438,6 @@ def test_handle_unicode(rule_runner: RuleRunner) -> None: assert_deps_parsed(rule_runner, "x = 'äbç'", expected_imports={}) -@skip_unless_python27_present -def test_works_with_python2(rule_runner: RuleRunner) -> None: - content = dedent( - """\ - # -*- coding: utf-8 -*- - print "Python 2 lives on." - - import demo - from project.demo import Demo - - __import__(u"pkg_resources") - __import__(b"treat.as.a.regular.import.not.a.string.import") - __import__(u"{}".format("interpolation")) - - importlib.import_module(b"dep.from.bytes") - importlib.import_module(u"dep.from.str") - importlib.import_module(u"dep.from.str_狗") - - b"\\xa0 a non-utf8 string, make sure we ignore it" - - try: import weak1 - except ImportError: import strong1 - else: import strong2 - finally: import strong3 - """ - ) - assert_deps_parsed( - rule_runner, - content, - constraints="==2.7.*", - expected_imports={ - "demo": ImpInfo(lineno=4, weak=False), - "project.demo.Demo": ImpInfo(lineno=5, weak=False), - "pkg_resources": ImpInfo(lineno=7, weak=False), - "treat.as.a.regular.import.not.a.string.import": ImpInfo(lineno=8, weak=False), - "dep.from.bytes": ImpInfo(lineno=11, weak=True), - "dep.from.str": ImpInfo(lineno=12, weak=True), - "dep.from.str_狗": ImpInfo(lineno=13, weak=True), - "weak1": ImpInfo(lineno=17, weak=True), - "strong1": ImpInfo(lineno=18, weak=False), - "strong2": ImpInfo(lineno=19, weak=False), - "strong3": ImpInfo(lineno=20, weak=False), - }, - ) - - @skip_unless_python38_present def test_works_with_python38(rule_runner: RuleRunner) -> None: content = dedent( diff --git a/src/python/pants/backend/python/framework/django/dependency_inference_test.py b/src/python/pants/backend/python/framework/django/dependency_inference_test.py index 39f198e3684..c569b333994 100644 --- a/src/python/pants/backend/python/framework/django/dependency_inference_test.py +++ b/src/python/pants/backend/python/framework/django/dependency_inference_test.py @@ -20,7 +20,6 @@ from pants.engine.rules import QueryRule from pants.engine.target import InferredDependencies from pants.testutil.python_interpreter_selection import ( - skip_unless_python27_present, skip_unless_python38_present, skip_unless_python39_present, ) @@ -170,12 +169,6 @@ def do_test_implicit_app_dependencies(rule_runner: RuleRunner, constraints: str) } -@skip_unless_python27_present -def test_works_with_python2(rule_runner: RuleRunner) -> None: - do_test_migration_dependencies(rule_runner, constraints="CPython==2.7.*") - do_test_implicit_app_dependencies(rule_runner, constraints="CPython==2.7.*") - - @skip_unless_python38_present def test_works_with_python38(rule_runner: RuleRunner) -> None: do_test_migration_dependencies(rule_runner, constraints="CPython==3.8.*") diff --git a/src/python/pants/backend/python/framework/django/detect_apps_test.py b/src/python/pants/backend/python/framework/django/detect_apps_test.py index 0b1426a982b..af2cf70da21 100644 --- a/src/python/pants/backend/python/framework/django/detect_apps_test.py +++ b/src/python/pants/backend/python/framework/django/detect_apps_test.py @@ -13,10 +13,9 @@ from pants.core.util_rules import stripped_source_files from pants.engine.environment import EnvironmentName from pants.testutil.python_interpreter_selection import ( - PY_27, + PY_38, PY_39, skip_unless_all_pythons_present, - skip_unless_python27_present, skip_unless_python37_present, skip_unless_python38_present, skip_unless_python39_present, @@ -52,10 +51,6 @@ def assert_apps_detected( py3_only = "async def i_will_parse_on_python3_not_on_python2():\n pass" else: py3_only = "" - if "2.7" in constraints2: - py2_only = "print 'I will parse on Python 2.7, not on Python 3'" - else: - py2_only = "" rule_runner.write_files( { "path/to/app1/BUILD": softwrap( @@ -84,9 +79,7 @@ class App1AppConfig(AppConfig): """ ), "another/path/app2/apps.py": softwrap( - f"""\ - {py2_only} - + """\ class App2AppConfig(AppConfig): name = "another.path.app2" label = "app2_label" @@ -124,11 +117,6 @@ class App3AppConfig(AppConfig): ) -@skip_unless_python27_present -def test_works_with_python2(rule_runner: RuleRunner) -> None: - assert_apps_detected(rule_runner, constraints1="CPython==2.7.*") - - @skip_unless_python37_present def test_works_with_python37(rule_runner: RuleRunner) -> None: assert_apps_detected(rule_runner, constraints1="CPython==3.7.*") @@ -144,6 +132,6 @@ def test_works_with_python39(rule_runner: RuleRunner) -> None: assert_apps_detected(rule_runner, constraints1="CPython==3.9.*") -@skip_unless_all_pythons_present(PY_27, PY_39) +@skip_unless_all_pythons_present(PY_38, PY_39) def test_partitioning_by_ics(rule_runner: RuleRunner) -> None: - assert_apps_detected(rule_runner, constraints1="CPython==3.9.*", constraints2="CPython==2.7.*") + assert_apps_detected(rule_runner, constraints1="CPython==3.8.*", constraints2="CPython==3.9.*") diff --git a/src/python/pants/backend/python/typecheck/mypy/rules_integration_test.py b/src/python/pants/backend/python/typecheck/mypy/rules_integration_test.py index a04bac94fd6..cb5c99b241a 100644 --- a/src/python/pants/backend/python/typecheck/mypy/rules_integration_test.py +++ b/src/python/pants/backend/python/typecheck/mypy/rules_integration_test.py @@ -39,8 +39,6 @@ from pants.testutil.python_interpreter_selection import ( all_major_minor_python_versions, skip_unless_all_pythons_present, - skip_unless_python27_and_python3_present, - skip_unless_python27_present, skip_unless_python38_present, skip_unless_python39_present, ) @@ -330,71 +328,6 @@ def add(x: int, y: int) -> str: assert f"{PACKAGE}/math/add.py:5" in result[0].stdout -@skip_unless_python27_present -def test_works_with_python27(rule_runner: PythonRuleRunner) -> None: - """A regression test that we can properly handle Python 2-only third-party dependencies. - - There was a bug that this would cause the runner PEX to fail to execute because it did not have - Python 3 distributions of the requirements. - - Also note that this Python 2 support should be automatic: Pants will tell MyPy to run with - `--py2` by detecting its use in interpreter constraints. - """ - rule_runner.write_files( - { - "mypy.lock": read_sibling_resource(__name__, "older_mypy_for_testing.lock"), - "BUILD": dedent( - """\ - # Both requirements are a) typed and b) compatible with Py2 and Py3. However, `x690` - # has a distinct wheel for Py2 vs. Py3, whereas libumi has a universal wheel. We expect - # both to be usable, even though libumi is not compatible with Py3. - - python_requirement( - name="libumi", - requirements=["libumi==0.0.2"], - ) - - python_requirement( - name="x690", - requirements=["x690==0.2.0"], - ) - """ - ), - f"{PACKAGE}/f.py": dedent( - """\ - from libumi import hello_world - from x690 import types - - print "Blast from the past!" - print hello_world() - 21 # MyPy should fail. You can't subtract an `int` from `bytes`. - """ - ), - f"{PACKAGE}/BUILD": "python_sources(interpreter_constraints=['==2.7.*'])", - } - ) - tgt = rule_runner.get_target(Address(PACKAGE, relative_file_path="f.py")) - result = run_mypy( - rule_runner, - [tgt], - extra_args=[ - "--python-resolves={'mypy':'mypy.lock'}", - "--mypy-install-from-resolve=mypy", - ], - ) - assert len(result) == 1 - assert result[0].exit_code == 1 - assert f"{PACKAGE}/f.py:5: error: Unsupported operand types" in result[0].stdout - # Confirm original issues not showing up. - assert "Failed to execute PEX file" not in result[0].stderr - assert ( - "Cannot find implementation or library stub for module named 'x690'" not in result[0].stdout - ) - assert ( - "Cannot find implementation or library stub for module named 'libumi'" - not in result[0].stdout - ) - - @skip_unless_python38_present def test_works_with_python38(rule_runner: PythonRuleRunner) -> None: """MyPy's typed-ast dependency does not understand Python 3.8, so we must instead run MyPy with @@ -435,69 +368,6 @@ def replaced(x: bool) -> str: assert_success(rule_runner, tgt) -@skip_unless_python27_and_python3_present -def test_uses_correct_python_version(rule_runner: PythonRuleRunner) -> None: - """We set `--python-version` automatically for the user, and also batch based on interpreter - constraints. - - This batching must consider transitive dependencies, so we use a more complex setup where the - dependencies are what have specific constraints that influence the batching. - """ - rule_runner.write_files( - { - "mypy.lock": read_sibling_resource(__name__, "older_mypy_for_testing.lock"), - f"{PACKAGE}/py2/__init__.py": dedent( - """\ - def add(x, y): - # type: (int, int) -> int - return x + y - """ - ), - f"{PACKAGE}/py2/BUILD": "python_sources(interpreter_constraints=['==2.7.*'])", - f"{PACKAGE}/py3/__init__.py": dedent( - """\ - def add(x: int, y: int) -> int: - return x + y - """ - ), - f"{PACKAGE}/py3/BUILD": "python_sources(interpreter_constraints=['>=3.8'])", - f"{PACKAGE}/__init__.py": "", - f"{PACKAGE}/uses_py2.py": "from project.py2 import add\nassert add(2, 2) == 4\n", - f"{PACKAGE}/uses_py3.py": "from project.py3 import add\nassert add(2, 2) == 4\n", - f"{PACKAGE}/BUILD": dedent( - """python_sources( - overrides={ - 'uses_py2.py': {'interpreter_constraints': ['==2.7.*']}, - 'uses_py3.py': {'interpreter_constraints': ['>=3.8']}, - } - ) - """ - ), - } - ) - py2_tgt = rule_runner.get_target(Address(PACKAGE, relative_file_path="uses_py2.py")) - py3_tgt = rule_runner.get_target(Address(PACKAGE, relative_file_path="uses_py3.py")) - - result = run_mypy( - rule_runner, - [py2_tgt, py3_tgt], - extra_args=[ - "--python-resolves={'mypy':'mypy.lock'}", - "--mypy-install-from-resolve=mypy", - ], - ) - assert len(result) == 2 - py2_result, py3_result = sorted(result, key=lambda res: res.partition_description or "") - - assert py2_result.exit_code == 0 - assert py2_result.partition_description == "['CPython==2.7.*']" - assert "Success: no issues found" in py2_result.stdout - - assert py3_result.exit_code == 0 - assert py3_result.partition_description == "['CPython>=3.8']" - assert "Success: no issues found" in py3_result.stdout - - def test_run_only_on_specified_files(rule_runner: PythonRuleRunner) -> None: rule_runner.write_files( { diff --git a/src/python/pants/backend/python/util_rules/dists_test.py b/src/python/pants/backend/python/util_rules/dists_test.py index 87fc7fe8bda..472f1da02b3 100644 --- a/src/python/pants/backend/python/util_rules/dists_test.py +++ b/src/python/pants/backend/python/util_rules/dists_test.py @@ -16,10 +16,7 @@ from pants.backend.python.util_rules.pex_requirements import PexRequirements from pants.engine.fs import CreateDigest, FileContent from pants.engine.internals.native_engine import Digest -from pants.testutil.python_interpreter_selection import ( - skip_unless_python27_present, - skip_unless_python39_present, -) +from pants.testutil.python_interpreter_selection import skip_unless_python39_present from pants.testutil.rule_runner import QueryRule, RuleRunner from pants.util.frozendict import FrozenDict @@ -70,11 +67,6 @@ def do_test_backend_shim(rule_runner: RuleRunner, constraints: str) -> None: assert res.wheel_path == f"dist/foobar-1.2.3-py{'2' if is_py2 else '3'}-none-any.whl" -@skip_unless_python27_present -def test_works_with_python2(rule_runner: RuleRunner) -> None: - do_test_backend_shim(rule_runner, constraints="CPython==2.7.*") - - @skip_unless_python39_present def test_works_with_python39(rule_runner: RuleRunner) -> None: do_test_backend_shim(rule_runner, constraints="CPython==3.9.*") diff --git a/src/python/pants/backend/python/util_rules/local_dists_pep660_test.py b/src/python/pants/backend/python/util_rules/local_dists_pep660_test.py index 1426461c9a2..0fc2e40380b 100644 --- a/src/python/pants/backend/python/util_rules/local_dists_pep660_test.py +++ b/src/python/pants/backend/python/util_rules/local_dists_pep660_test.py @@ -29,10 +29,7 @@ from pants.build_graph.address import Address from pants.engine.fs import CreateDigest, Digest, DigestContents, FileContent from pants.engine.internals.parametrize import Parametrize -from pants.testutil.python_interpreter_selection import ( - skip_unless_python27_present, - skip_unless_python39_present, -) +from pants.testutil.python_interpreter_selection import skip_unless_python39_present from pants.testutil.python_rule_runner import PythonRuleRunner from pants.testutil.rule_runner import QueryRule from pants.util.frozendict import FrozenDict @@ -86,16 +83,7 @@ def do_test_backend_wrapper(rule_runner: PythonRuleRunner, constraints: str) -> ) res = rule_runner.request(PEP660BuildResult, [req]) - is_py2 = "2.7" in constraints - assert ( - res.editable_wheel_path - == f"dist/foobar-1.2.3-0.editable-{'py2.' if is_py2 else ''}py3-none-any.whl" - ) - - -@skip_unless_python27_present -def test_works_with_python2(rule_runner: PythonRuleRunner) -> None: - do_test_backend_wrapper(rule_runner, constraints="CPython==2.7.*") + assert res.editable_wheel_path == "dist/foobar-1.2.3-0.editable-py3-none-any.whl" @skip_unless_python39_present diff --git a/src/python/pants_release/generate_github_workflows.py b/src/python/pants_release/generate_github_workflows.py index 88af2b3478b..65aab1f88f8 100644 --- a/src/python/pants_release/generate_github_workflows.py +++ b/src/python/pants_release/generate_github_workflows.py @@ -450,7 +450,7 @@ def runs_on(self) -> list[str]: elif self.platform == Platform.MACOS10_15_X86_64: ret += ["macOS-10.15-X64"] elif self.platform == Platform.LINUX_X86_64: - ret += ["ubuntu-20.04"] + ret += ["ubuntu-22.04"] elif self.platform == Platform.LINUX_ARM64: ret += [ "runs-on",