Repository: pantsbuild/pants

Issue:
Tailor pex_binary targets for a __main__.py
Today we detect `if __name__ == "__main__"` in a file as indicating that it's an entry point to a binary.

However in Python a `__main__.py` can also act as the entry point to the package containing it, so 
it would be great for tailor to generate the appropriate target in that case.


Discussion:

Resolving patch:
diff --git a/src/python/pants/backend/python/goals/tailor.py b/src/python/pants/backend/python/goals/tailor.py
--- a/src/python/pants/backend/python/goals/tailor.py
+++ b/src/python/pants/backend/python/goals/tailor.py
@@ -161,13 +161,14 @@ def add_req_targets(files: Iterable[str], alias: str, target_name: str) -> None:
     if python_setup.tailor_pex_binary_targets:
         # Find binary targets.
 
-        # Get all files whose content indicates that they are entry points.
+        # Get all files whose content indicates that they are entry points or are __main__.py files.
         digest_contents = await Get(DigestContents, PathGlobs, all_py_files_globs)
+        all_main_py = await Get(Paths, PathGlobs, req.search_paths.path_globs("__main__.py"))
         entry_points = [
             file_content.path
             for file_content in digest_contents
             if is_entry_point(file_content.content)
-        ]
+        ] + list(all_main_py.files)
 
         # Get the modules for these entry points.
         src_roots = await Get(
diff --git a/src/python/pants/backend/python/subsystems/setup.py b/src/python/pants/backend/python/subsystems/setup.py
--- a/src/python/pants/backend/python/subsystems/setup.py
+++ b/src/python/pants/backend/python/subsystems/setup.py
@@ -450,8 +450,8 @@ class PythonSetup(Subsystem):
         default=True,
         help=softwrap(
             """
-            If true, add `pex_binary` targets for Python files with a `__main__` clause with the
-            `tailor` goal.
+            If true, add `pex_binary` targets for Python files named `__main__.py` or with a
+            `__main__` clause with the `tailor` goal.
             """
         ),
         advanced=True,


Test patch:
diff --git a/src/python/pants/backend/python/goals/tailor_test.py b/src/python/pants/backend/python/goals/tailor_test.py
--- a/src/python/pants/backend/python/goals/tailor_test.py
+++ b/src/python/pants/backend/python/goals/tailor_test.py
@@ -217,13 +217,16 @@ def test_find_putative_targets_for_entry_points(rule_runner: RuleRunner) -> None
                 "pex_binary(name='main1', entry_point='main1.py')\n"
                 "pex_binary(name='main2', entry_point='foo.main2')\n"
             ),
+            "src/python/foo/__main__.py": "",
         }
     )
     pts = rule_runner.request(
         PutativeTargets,
         [
             PutativePythonTargetsRequest(PutativeTargetsSearchPaths(("",))),
-            AllOwnedSources([f"src/python/foo/{name}" for name in mains]),
+            AllOwnedSources(
+                [f"src/python/foo/{name}" for name in mains] + ["src/python/foo/__main__.py"]
+            ),
         ],
     )
     assert (
@@ -236,6 +239,13 @@ def test_find_putative_targets_for_entry_points(rule_runner: RuleRunner) -> None
                     [],
                     kwargs={"entry_point": "main3.py"},
                 ),
+                PutativeTarget.for_target_type(
+                    PexBinary,
+                    "src/python/foo",
+                    "__main__",
+                    [],
+                    kwargs={"entry_point": "__main__.py"},
+                ),
             ]
         )
         == pts