Skip to main content

postcard_bindgen/package/
pip_module.rs

1use core::borrow::Borrow;
2use std::{
3    fs::{create_dir_all, File},
4    io::{self, Write},
5    path::Path,
6};
7
8use postcard_bindgen_core::{
9    code_gen::python::{generate, GenerationSettings},
10    registry::ContainerCollection,
11};
12
13use super::{PackageInfo, Version};
14
15/// Builds a pip module from [ContainerCollection].
16///
17/// # Example
18/// ```
19/// # use postcard_bindgen::{python::{build_package, GenerationSettings}, PackageInfo, PostcardBindings, generate_bindings};
20/// # use serde::Serialize;
21/// #[derive(Serialize, PostcardBindings)]
22/// struct Test {
23///    field: u8
24/// }
25///
26/// # fn main() {
27/// let parent_dir = std::env::current_dir().unwrap();
28/// let package_info = PackageInfo {
29///    name: "test_package".into(),
30///    version: "0.1.0".try_into().unwrap()
31/// };
32///
33/// build_package(parent_dir.as_path(), package_info, GenerationSettings::enable_all(), generate_bindings!(Test));
34/// # }
35/// ```
36pub fn build_pip_module(
37    parent_dir: &Path,
38    package_info: PackageInfo,
39    gen_settings: impl Borrow<GenerationSettings>,
40    containers: ContainerCollection,
41) -> io::Result<()> {
42    let mut dir = parent_dir.to_path_buf();
43    dir.push(package_info.name.as_str());
44    std::fs::create_dir_all(&dir)?;
45
46    let package_name = package_info.name.replace("-", "_");
47
48    let mod_toml = mod_file_src(&package_name, &package_info.version);
49
50    let mut mod_toml_path = dir.to_owned();
51    mod_toml_path.push("pyproject.toml");
52    File::create(mod_toml_path.as_path())?.write_all(mod_toml.as_bytes())?;
53
54    dir.push("src");
55    dir.push(&package_name);
56
57    std::fs::create_dir_all(&dir)?;
58
59    let exports = generate(containers, gen_settings, package_info.name);
60
61    let bindings_export_path = dir.to_owned();
62
63    for file in exports.files {
64        let path = bindings_export_path.join(format!("{}.py", file.content_type));
65        let dir_path = {
66            let mut p = path.clone();
67            p.pop();
68            p
69        };
70        create_dir_all(dir_path)?;
71        File::create(path.as_path())?
72            .write_all(file.content.to_file_string().unwrap().as_bytes())?;
73    }
74
75    Ok(())
76}
77
78fn mod_file_src(package_name: impl AsRef<str>, package_version: &Version) -> String {
79    let package_name = package_name.as_ref();
80    let package_version = package_version.to_string();
81
82    format!(
83        "
84[project]
85name = \"{package_name}\"
86version = \"{package_version}\"
87authors = [
88  {{ name=\"postcard-bindgen\" }},
89]
90description = \"Auto generated bindings for postcard format serializing and deserializing python to and from bytes.\"
91requires-python = \">=3.8\"
92",
93    )
94}