Skip to content

Add more build-info functions to c-api#8216

Open
bschoenmaeckers wants to merge 1 commit into
RustPython:mainfrom
bschoenmaeckers:c-api-buildinfo
Open

Add more build-info functions to c-api#8216
bschoenmaeckers wants to merge 1 commit into
RustPython:mainfrom
bschoenmaeckers:c-api-buildinfo

Conversation

@bschoenmaeckers

@bschoenmaeckers bschoenmaeckers commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features
    • Added runtime system metadata access (build, compiler, copyright, and platform) via standard interfaces.
    • Exposed additional system details through sys constants, including build info and compiler, alongside updated visibility for existing version-related constants.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: eecfe4ab-cd05-4024-9c07-46d6f4d98bf9

📥 Commits

Reviewing files that changed from the base of the PR and between 44e1a4c and c567388.

📒 Files selected for processing (2)
  • crates/capi/src/pylifecycle.rs
  • crates/vm/src/stdlib/sys.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • crates/vm/src/stdlib/sys.rs
  • crates/capi/src/pylifecycle.rs

📝 Walkthrough

Walkthrough

Publicizes build metadata constants in sys and adds four C-ABI getters in pylifecycle that return those values as C-compatible strings.

Changes

Build metadata C API exposure

Layer / File(s) Summary
Publicize sys module build metadata constants
crates/vm/src/stdlib/sys.rs
Re-exports BUILD_INFO, COMPILER, COPYRIGHT, PLATFORM, and VERSION at module scope, and makes COPYRIGHT, VERSION, BUILD_INFO, and COMPILER public inside the inner sys module.
Add extern C functions for build metadata
crates/capi/src/pylifecycle.rs
Imports rustpython_vm::stdlib::sys and adds Py_GetBuildInfo, Py_GetCompiler, Py_GetCopyright, and Py_GetPlatform, each returning a raw pointer from a lazily initialized CString built from the matching constant.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: ShaharNaveh, youknowone

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change: adding new build-info related C-API functions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/capi/src/pylifecycle.rs`:
- Around line 84-115: The four getter functions are duplicated and should be
refactored into a macro-based helper. Extract the shared CString/LazyLock/as_ptr
logic into a single reusable macro or helper and parameterize only the differing
sys constant, static identifier, and panic text for Py_GetBuildInfo,
Py_GetCompiler, Py_GetCopyright, and Py_GetPlatform. Keep the public extern "C"
function names unchanged and apply the same pattern consistently if
Py_GetVersion or similar getters in pylifecycle.rs use the same structure.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: d582c5db-c613-42ea-a2b7-5f7d60708967

📥 Commits

Reviewing files that changed from the base of the PR and between 3f9d80b and 44e1a4c.

📒 Files selected for processing (2)
  • crates/capi/src/pylifecycle.rs
  • crates/vm/src/stdlib/sys.rs

Comment on lines +84 to +115
#[unsafe(no_mangle)]
pub extern "C" fn Py_GetBuildInfo() -> *const c_char {
static BUILD_INFO: LazyLock<CString> = LazyLock::new(|| {
CString::new(sys::BUILD_INFO).expect("build info must not contain interior NULs")
});
BUILD_INFO.as_ptr()
}

#[unsafe(no_mangle)]
pub extern "C" fn Py_GetCompiler() -> *const c_char {
static COMPILER: LazyLock<CString> = LazyLock::new(|| {
CString::new(sys::COMPILER).expect("compiler must not contain interior NULs")
});
COMPILER.as_ptr()
}

#[unsafe(no_mangle)]
pub extern "C" fn Py_GetCopyright() -> *const c_char {
static COPYRIGHT: LazyLock<CString> = LazyLock::new(|| {
CString::new(sys::COPYRIGHT).expect("copyright must not contain interior NULs")
});
COPYRIGHT.as_ptr()
}

#[unsafe(no_mangle)]
pub extern "C" fn Py_GetPlatform() -> *const c_char {
static PLATFORM: LazyLock<CString> = LazyLock::new(|| {
CString::new(sys::PLATFORM).expect("platform must not contain interior NULs")
});
PLATFORM.as_ptr()
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Deduplicate the four near-identical build-metadata functions with a macro.

Py_GetBuildInfo, Py_GetCompiler, Py_GetCopyright, and Py_GetPlatform differ only in the source constant, static name, and panic message — everything else is copy-pasted.

♻️ Proposed macro-based refactor
+macro_rules! build_metadata_getter {
+    ($fn_name:ident, $const_name:path, $what:literal) => {
+        #[unsafe(no_mangle)]
+        pub extern "C" fn $fn_name() -> *const c_char {
+            static VALUE: LazyLock<CString> = LazyLock::new(|| {
+                CString::new($const_name).expect(concat!($what, " must not contain interior NULs"))
+            });
+            VALUE.as_ptr()
+        }
+    };
+}
+
+build_metadata_getter!(Py_GetBuildInfo, sys::BUILD_INFO, "build info");
+build_metadata_getter!(Py_GetCompiler, sys::COMPILER, "compiler");
+build_metadata_getter!(Py_GetCopyright, sys::COPYRIGHT, "copyright");
+build_metadata_getter!(Py_GetPlatform, sys::PLATFORM, "platform");
-#[unsafe(no_mangle)]
-pub extern "C" fn Py_GetBuildInfo() -> *const c_char {
-    static BUILD_INFO: LazyLock<CString> = LazyLock::new(|| {
-        CString::new(sys::BUILD_INFO).expect("build info must not contain interior NULs")
-    });
-    BUILD_INFO.as_ptr()
-}
-
-#[unsafe(no_mangle)]
-pub extern "C" fn Py_GetCompiler() -> *const c_char {
-    static COMPILER: LazyLock<CString> = LazyLock::new(|| {
-        CString::new(sys::COMPILER).expect("compiler must not contain interior NULs")
-    });
-    COMPILER.as_ptr()
-}
-
-#[unsafe(no_mangle)]
-pub extern "C" fn Py_GetCopyright() -> *const c_char {
-    static COPYRIGHT: LazyLock<CString> = LazyLock::new(|| {
-        CString::new(sys::COPYRIGHT).expect("copyright must not contain interior NULs")
-    });
-    COPYRIGHT.as_ptr()
-}
-
-#[unsafe(no_mangle)]
-pub extern "C" fn Py_GetPlatform() -> *const c_char {
-    static PLATFORM: LazyLock<CString> = LazyLock::new(|| {
-        CString::new(sys::PLATFORM).expect("platform must not contain interior NULs")
-    });
-    PLATFORM.as_ptr()
-}

As per coding guidelines: "When branches differ only in a value but share common logic, extract the differing value first, then call the common logic once to avoid duplicate code."

#!/bin/bash
# Check whether Py_GetVersion (pre-existing) follows the same repeated pattern,
# and whether existing pyo3-based tests cover similar getters.
ast-grep run --pattern 'pub extern "C" fn Py_GetVersion() -> *const c_char { $$$ }' --lang rust crates/capi/src/pylifecycle.rs
rg -n -A5 -B2 '"Py_Get' crates/capi/src/pylifecycle.rs
rg -n 'fn test' -A10 crates/capi/src/pylifecycle.rs | rg -n 'Py_Get' -B5
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/capi/src/pylifecycle.rs` around lines 84 - 115, The four getter
functions are duplicated and should be refactored into a macro-based helper.
Extract the shared CString/LazyLock/as_ptr logic into a single reusable macro or
helper and parameterize only the differing sys constant, static identifier, and
panic text for Py_GetBuildInfo, Py_GetCompiler, Py_GetCopyright, and
Py_GetPlatform. Keep the public extern "C" function names unchanged and apply
the same pattern consistently if Py_GetVersion or similar getters in
pylifecycle.rs use the same structure.

Source: Coding guidelines

const API_VERSION: u32 = 0x0; // what C api?
#[pyattr(name = "copyright")]
const COPYRIGHT: &str = "Copyright (c) 2019 RustPython Team";
pub const COPYRIGHT: &str = "Copyright (c) 2019 RustPython Team";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, another suggestion.
let's define this as

Suggested change
pub const COPYRIGHT: &str = "Copyright (c) 2019 RustPython Team";
pub const COPYRIGHT: &CStr = c"Copyright (c) 2019 RustPython Team";

Then add a IntoPyObject conversion from &CStr to String to ignore the tail null char.
This will not hurt any RustPython use case and also will make C api happier without LazyLock

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants