Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate the # Dependees column name in the py-constraints summary. #17399

Merged
merged 1 commit into from
Oct 31, 2022
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
Expand Up @@ -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.
Expand Down Expand Up @@ -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.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -39,19 +40,37 @@ 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.
"""
),
)

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
Expand All @@ -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(
Expand Down Expand Up @@ -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
)
Expand All @@ -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,
)
]

Expand All @@ -128,7 +157,7 @@ async def py_constraints(
"Constraints",
"Transitive Constraints",
"# Dependencies",
"# Dependees",
dependents_header,
],
)
writer.writeheader()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down