|
1 | 1 | import logging |
2 | 2 | import os |
| 3 | +import sys |
3 | 4 | import typing as t |
4 | 5 | from pathlib import Path |
5 | 6 |
|
|
13 | 14 | LOG = logging.getLogger(__name__) |
14 | 15 |
|
15 | 16 |
|
16 | | -def _path_to_module(path): |
17 | | - """ |
18 | | - Convert a path to a Python module to its module representation. |
19 | | -
|
20 | | - Example: plux/core/test -> plux.core.test |
21 | | - """ |
22 | | - return ".".join(Path(path).with_suffix("").parts) |
23 | | - |
24 | | - |
25 | 17 | class HatchlingPackageFinder(PackageFinder): |
26 | 18 | """ |
27 | 19 | Uses hatchling's BuilderConfig abstraction to enumerate packages. |
28 | 20 |
|
29 | | - TODO: this might not be 100% correct and needs more thorough testing with different scenarios. |
| 21 | + TODO: include/exclude configuration of packages in hatch needs more thorough testing with different scenarios. |
30 | 22 | """ |
31 | 23 |
|
32 | 24 | builder_config: BuilderConfig |
@@ -111,27 +103,44 @@ def __init__(self, workdir: str = None): |
111 | 103 | "Hatchling integration currently only works with entrypoint_build_mode=manual" |
112 | 104 | ) |
113 | 105 |
|
114 | | - # FIXME it's unclear whether this will really hold for all configs. most configs we assume will build a wheel, |
115 | | - # and any associated package configuration will come from there. so currently we make the wheel build config |
116 | | - # the source of truth, but we should revisit this once we know more about hatch build configurations. |
| 106 | + # we assume that a wheel will be the source of truth for the packages finally ending up in the distribution. |
| 107 | + # therefore we care foremost about the wheel configuration. this also builds on the assumption that building |
| 108 | + # the wheel from the local sources, and the sdist, will be the same. |
117 | 109 | self.builder = WheelBuilder(workdir) |
118 | 110 |
|
| 111 | + @property |
| 112 | + def hatchling_config(self) -> BuilderConfig: |
| 113 | + return self.builder.config |
| 114 | + |
119 | 115 | def create_package_finder(self) -> PackageFinder: |
120 | 116 | return HatchlingPackageFinder( |
121 | 117 | self.hatchling_config, |
122 | 118 | exclude=self.config.exclude, |
123 | 119 | include=self.config.include, |
124 | 120 | ) |
125 | 121 |
|
126 | | - @property |
127 | | - def hatchling_config(self) -> BuilderConfig: |
128 | | - return self.builder.config |
129 | | - |
130 | 122 | def find_plux_index_file(self) -> Path: |
131 | 123 | # TODO: extend as soon as we support EntryPointBuildMode = build-hook |
132 | 124 | return Path(self.hatchling_config.root, self.config.entrypoint_static_file) |
133 | 125 |
|
134 | 126 | def find_entry_point_file(self) -> Path: |
135 | | - # TODO: we'll assume that `pip install -e .` is used, and therefore the entrypoints file will be in the |
136 | | - # .dist-info metadata directory |
137 | | - raise NotImplementedError |
| 127 | + # we assume that `pip install -e .` is used, and therefore the entrypoints file used during local execution |
| 128 | + # will be in the .dist-info metadata directory in the sys path |
| 129 | + metadata_dir = f"{self.builder.artifact_project_id}.dist-info" |
| 130 | + |
| 131 | + for path in sys.path: |
| 132 | + metadata_path = os.path.join(path, metadata_dir) |
| 133 | + if not os.path.exists(metadata_path): |
| 134 | + continue |
| 135 | + |
| 136 | + return Path(metadata_path) / "entry_points.txt" |
| 137 | + |
| 138 | + raise FileNotFoundError(f"No metadata found for {self.builder.artifact_project_id} in sys path") |
| 139 | + |
| 140 | + def build_entrypoints(self): |
| 141 | + # TODO: currently this just replicates the manual build mode. |
| 142 | + path = os.path.join(os.getcwd(), self.config.entrypoint_static_file) |
| 143 | + print(f"discovering plugins and writing to {path} ...") |
| 144 | + builder = self.create_plugin_index_builder() |
| 145 | + with open(path, "w") as fd: |
| 146 | + builder.write(fd, output_format="ini") |
0 commit comments