diff --git a/docs/markdown/Python/python/python-interpreter-compatibility.md b/docs/markdown/Python/python/python-interpreter-compatibility.md index 3b57a82c6d5..18f6a7030aa 100644 --- a/docs/markdown/Python/python/python-interpreter-compatibility.md +++ b/docs/markdown/Python/python/python-interpreter-compatibility.md @@ -61,7 +61,7 @@ Python 2-only target, which Pants will validate. It is possible for a target to have more precise interpreter constraints than its transitive dependencies. For example, if you have a common helper file `utils.py` that works with both -Python 2.7 and 3.5 (`['==2.7.*', '>=3.5']`), it is legal for a dependee like `app.py` to use more +Python 2.7 and 3.5 (`['==2.7.*', '>=3.5']`), it is legal for a dependent like `app.py` to use more precise constraints like `['==3.7.*']`. It is often useful for helper code to work with multiple Python versions, while specific "root" targets (tests, apps, and binaries) have more specific constraints. @@ -128,16 +128,16 @@ You can run `./pants py-constraints --summary` for Pants to generate a CSV givin We recommend then importing this CSV into a tool like Pandas or Excel to filter/sort the data. -The `# Dependees` column is useful to see how impactful it is to port a file, and the `# Dependencies` can be useful to see how easy it would be to port. +The `# Dependents` column is useful to see how impactful it is to port a file, and the `# Dependencies` can be useful to see how easy it would be to port. > 📘 Tips for Python 2 -> Python 3 migrations > > While every project will have different needs and scope, there are a few best practices with Pants that will allow for a more successful migration. > > - Start by setting the `interpreter_constraints` option in `[python]` to describe the status of the majority of your targets. If most are only compatible with Python 2, set it to `['==2.7.*']`. If most are compatible with Python 2 _and_ Python 3, set to `['==2.7', '>=3.5']`. If most are only compatible with Python 3, set to `[>=3.5]`. For any targets that don't match these global constraints, override with the `interpreter_constraints` field. -> - Run `./pants py-constraints --summary` and sort by `# Dependees` from Z to A to find your most-used files. Focus on getting these targets to be compatible with Python 2 and 3. You may want to also sub-sort the CSV by `# Dependencies` to find what is easiest to port. +> - Run `./pants py-constraints --summary` and sort by `# Dependents` from Z to A to find your most-used files. Focus on getting these targets to be compatible with Python 2 and 3. You may want to also sub-sort the CSV by `# Dependencies` to find what is easiest to port. > - Once >40% of your targets work with both Python 2 and Python 3, change the `interpreter_constraints` option in `[python]` to specify compatibility with both Python 2.7 and Python 3 so that all new code uses this by default. -> - For files with no or few dependencies, change them to Python 3-only when possible so that you can start using all the neat new Python 3 features like f-strings! Use the CSV from `./pants py-constraints --summary` to find these. You can also do this if every "dependee" target works exclusively with Python 3, which you can find by the `Transitive Constraints` column and by running `./pants py-constraints path/to/file.py`. +> - For files with no or few dependencies, change them to Python 3-only when possible so that you can start using all the neat new Python 3 features like f-strings! Use the CSV from `./pants py-constraints --summary` to find these. You can also do this if every dependent target works exclusively with Python 3, which you can find by the `Transitive Constraints` column and by running `./pants py-constraints path/to/file.py`. > > Check out [this blog post](https://enterprise.foursquare.com/intersections/article/how-our-intern-led-pants-migration-to-python-3/) on Pants' own migration to Python 3 in 2019 for more general tips on Python 3 migrations. diff --git a/src/python/pants/backend/python/mixed_interpreter_constraints/py_constraints.py b/src/python/pants/backend/python/mixed_interpreter_constraints/py_constraints.py index 01e0cb88a42..73dbd08b3a2 100644 --- a/src/python/pants/backend/python/mixed_interpreter_constraints/py_constraints.py +++ b/src/python/pants/backend/python/mixed_interpreter_constraints/py_constraints.py @@ -10,6 +10,7 @@ from pants.backend.python.subsystems.setup import PythonSetup from pants.backend.python.target_types import InterpreterConstraintsField from pants.backend.python.util_rules.interpreter_constraints import InterpreterConstraints +from pants.base.deprecated import warn_or_error from pants.engine.addresses import Addresses from pants.engine.console import Console from pants.engine.goal import Goal, GoalSubsystem, Outputting @@ -39,12 +40,12 @@ class PyConstraintsSubsystem(Outputting, GoalSubsystem): """ Output a CSV summary of interpreter constraints for your whole repository. The headers are `Target`, `Constraints`, `Transitive Constraints`, `# Dependencies`, - and `# Dependees`. + and `# Dependents` (or `# Dependees`, if summary_use_new_header is False). This information can be useful when prioritizing a migration from one Python version to - another (e.g. to Python 3). Use `# Dependencies` and `# Dependees` to help prioritize + another (e.g. to Python 3). Use `# Dependencies` and `# Dependents` to help prioritize which targets are easiest to port (low # dependencies) and highest impact to port - (high # dependees). + (high # dependents). Use a tool like Pandas or Excel to process the CSV. Use the option `--py-constraints-output-file=summary.csv` to write directly to a file. @@ -52,6 +53,24 @@ class PyConstraintsSubsystem(Outputting, GoalSubsystem): ), ) + summary_use_new_header = BoolOption( + default=False, + help=softwrap( + """ + If False, use the legacy, misleading `#Dependees` header name in the summary CSV table. + If True, will use the new, more accurate, `# Dependents` name for the same column. + + This is a temporary option to ease migration to the new header name. Set this option to + True to start working with the new header. + + This option's default value will change to True in 2.16.x, and it will be deprecated + in that version. + + This option, and the ability to use the old name, will be removed entirely in 2.17.x. + """ + ), + ) + class PyConstraintsGoal(Goal): subsystem_cls = PyConstraintsSubsystem @@ -68,6 +87,16 @@ async def py_constraints( union_membership: UnionMembership, ) -> PyConstraintsGoal: if py_constraints_subsystem.summary: + if not py_constraints_subsystem.summary_use_new_header: + warn_or_error( + "2.17.0.dev0", + "the old, misleading, `# Dependees` header", + "Set --summary-use-new-header to true to start using the new `# Dependents` header.", + ) + + dependents_header = ( + "# Dependents" if py_constraints_subsystem.summary_use_new_header else "# Dependees" + ) if addresses: console.print_stderr( softwrap( @@ -98,7 +127,7 @@ async def py_constraints( for transitive_targets in transitive_targets_per_tgt ] - dependees_per_root = await MultiGet( + dependents_per_root = await MultiGet( Get(Dependents, DependentsRequest([tgt.address], transitive=True, include_roots=False)) for tgt in all_python_targets ) @@ -109,14 +138,14 @@ async def py_constraints( "Constraints": str(constraints), "Transitive Constraints": str(transitive_constraints), "# Dependencies": len(transitive_targets.dependencies), - "# Dependees": len(dependees), + dependents_header: len(dependents), } - for tgt, constraints, transitive_constraints, transitive_targets, dependees in zip( + for tgt, constraints, transitive_constraints, transitive_targets, dependents in zip( all_python_targets, constraints_per_tgt, transitive_constraints_per_tgt, transitive_targets_per_tgt, - dependees_per_root, + dependents_per_root, ) ] @@ -128,7 +157,7 @@ async def py_constraints( "Constraints", "Transitive Constraints", "# Dependencies", - "# Dependees", + dependents_header, ], ) writer.writeheader() diff --git a/src/python/pants/backend/python/mixed_interpreter_constraints/py_constraints_test.py b/src/python/pants/backend/python/mixed_interpreter_constraints/py_constraints_test.py index f1e875823e3..7593f1d6cc5 100644 --- a/src/python/pants/backend/python/mixed_interpreter_constraints/py_constraints_test.py +++ b/src/python/pants/backend/python/mixed_interpreter_constraints/py_constraints_test.py @@ -110,10 +110,10 @@ def test_render_constraints(rule_runner: RuleRunner) -> None: def test_constraints_summary(rule_runner: RuleRunner) -> None: write_files(rule_runner) - result = run_goal(rule_runner, ["--summary"]) + result = run_goal(rule_runner, ["--summary", "--summary-use-new-header"]) assert result.stdout == dedent( """\ - Target,Constraints,Transitive Constraints,# Dependencies,# Dependees\r + Target,Constraints,Transitive Constraints,# Dependencies,# Dependents\r app/f.py,CPython==3.7.*,"CPython==2.7.*,==3.7.*,>=3.6 OR CPython==3.7.*,>=3.5,>=3.6",2,1\r lib1/f.py,CPython==2.7.* OR CPython>=3.5,CPython==2.7.* OR CPython>=3.5,0,3\r lib2/f.py,CPython>=3.6,CPython>=3.6,0,3\r