python_proto_importer/commands/
build.rs1use crate::config::{AppConfig, Backend};
2use crate::generator::protoc::ProtocRunner;
3use crate::postprocess::add_pyright_header;
4use crate::postprocess::apply::apply_rewrites_in_tree;
5use crate::postprocess::create_packages;
6use crate::postprocess::fds::{collect_generated_basenames_from_bytes, load_fds_from_bytes};
7use crate::postprocess::rel_imports::scan_and_report;
8use crate::verification::import_test::verify;
9use anyhow::{Context, Result};
10use std::path::Path;
11
12pub fn build(pyproject: Option<&str>, no_verify: bool, _postprocess_only: bool) -> Result<()> {
54 let cfg = AppConfig::load(pyproject.map(Path::new)).context("failed to load config")?;
55 tracing::info!(?cfg.backend, out=%cfg.out.display(), "build start");
56
57 let allowed_basenames = if _postprocess_only {
58 if !cfg.out.exists() {
59 anyhow::bail!(
60 "--postprocess-only: output directory does not exist: {}",
61 cfg.out.display()
62 );
63 }
64 tracing::info!("postprocess-only mode: skip generation");
65 None
66 } else {
67 match cfg.backend {
68 Backend::Protoc => {
69 let runner = ProtocRunner::new(&cfg);
70 let fds_bytes = runner.generate()?;
71 let _pool = load_fds_from_bytes(&fds_bytes).context("decode FDS failed")?;
72 Some(
73 collect_generated_basenames_from_bytes(&fds_bytes)
74 .context("collect basenames from FDS failed")?,
75 )
76 }
77 Backend::Buf => {
78 tracing::warn!("buf backend is not implemented yet");
79 None
80 }
81 }
82 };
83
84 if cfg.postprocess.create_package {
85 let created = create_packages(&cfg.out)?;
86 tracing::info!("created __init__.py: {}", created);
87 }
88
89 let (files, hits) =
90 scan_and_report(&cfg.out).context("scan relative-import candidates failed")?;
91 tracing::info!(
92 "relative-import candidates: files={}, lines={}",
93 files,
94 hits
95 );
96
97 if cfg.postprocess.relative_imports {
98 let modified = apply_rewrites_in_tree(
99 &cfg.out,
100 cfg.postprocess.exclude_google,
101 &cfg.postprocess.module_suffixes,
102 allowed_basenames.as_ref(),
103 )
104 .context("apply relative-import rewrites failed")?;
105 tracing::info!(
106 "relative-import rewrites applied: {} files modified",
107 modified
108 );
109 }
110
111 if cfg.postprocess.pyright_header {
112 let added = add_pyright_header(&cfg.out)?;
113 if added > 0 {
114 tracing::info!("pyright header added: {} files", added);
115 }
116 }
117
118 if !no_verify {
119 verify(&cfg)?;
120 }
121 Ok(())
122}