forked from pantsbuild/pants
-
Notifications
You must be signed in to change notification settings - Fork 0
/
importable_python_sources.py
54 lines (43 loc) · 2.09 KB
/
importable_python_sources.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# Copyright 2020 Pants project contributors (see CONTRIBUTORS.md).
# Licensed under the Apache License, Version 2.0 (see LICENSE).
from dataclasses import dataclass
from pants.backend.python.rules.inject_init import InitInjectedSnapshot, InjectInitRequest
from pants.backend.python.rules.inject_init import rules as inject_init_rules
from pants.backend.python.target_types import PythonSources
from pants.core.target_types import FilesSources, ResourcesSources
from pants.core.util_rules import determine_source_files
from pants.core.util_rules.determine_source_files import AllSourceFilesRequest, SourceFiles
from pants.engine.fs import Snapshot
from pants.engine.rules import RootRule, rule
from pants.engine.selectors import Get
from pants.engine.target import Sources, Targets
@dataclass(frozen=True)
class ImportablePythonSources:
"""Sources that can be imported and used by Python, e.g. with tools like Pytest or with `./pants
run`.
Specifically, this will filter out to only have Python, resources(), and files() targets; will
strip source roots, e.g. `src/python/f.py` -> `f.py`; and will add any missing
`__init__.py` files to ensure that modules are recognized correctly.
Not every Python application will need to request this type. For example, autoformatters like
Black never need to actually import and run the Python code, so they do not need to use this.
"""
snapshot: Snapshot
@rule
async def prepare_python_sources(targets: Targets) -> ImportablePythonSources:
stripped_sources = await Get[SourceFiles](
AllSourceFilesRequest(
(tgt.get(Sources) for tgt in targets),
for_sources_types=(PythonSources, ResourcesSources, FilesSources),
enable_codegen=True,
strip_source_roots=True,
)
)
init_injected = await Get[InitInjectedSnapshot](InjectInitRequest(stripped_sources.snapshot))
return ImportablePythonSources(init_injected.snapshot)
def rules():
return [
prepare_python_sources,
*determine_source_files.rules(),
*inject_init_rules(),
RootRule(Targets),
]