Skip to content

Commit 31daf31

Browse files
authored
Merge pull request #1 from inference-labs-inc/feat/optional-pyo3
Introduce optional pyo3 dependency for pure Rust consumption
2 parents bff16fd + 4f1a582 commit 31daf31

File tree

5 files changed

+23
-28
lines changed

5 files changed

+23
-28
lines changed

Cargo.toml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ crate-type = ["cdylib", "rlib"]
1010

1111
[dependencies]
1212
sp-core = "34.0.0"
13-
pyo3 = { version = "0.26.0", features = ["generate-import-lib"] }
13+
pyo3 = { version = "0.26.0", features = ["generate-import-lib"], optional = true }
1414
bip39 = { version = "2.0.0", features = ["rand"] }
1515
hex = "0.4.3"
1616
colored = "2.1.0"
@@ -37,7 +37,6 @@ optional = true
3737
features = ["vendored"]
3838

3939
[features]
40-
extension-module = ["pyo3/extension-module"]
40+
python-bindings = ["dep:pyo3", "pyo3/extension-module"]
4141
vendored-openssl = ["openssl-sys/vendored"]
42-
default = ["extension-module"]
43-
python-bindings = []
42+
default = ["python-bindings"]

src/keyfile.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use fernet::Fernet;
1212
use base64::{engine::general_purpose, Engine as _};
1313
use passwords::analyzer;
1414
use passwords::scorer;
15-
use pyo3::pyfunction;
1615
use serde_json::json;
1716

1817
use crate::errors::KeyFileError;
@@ -164,25 +163,25 @@ pub fn ask_password(validation_required: bool) -> Result<String, KeyFileError> {
164163
}
165164

166165
/// Returns `true` if the keyfile data is NaCl encrypted.
167-
#[pyfunction]
166+
#[cfg_attr(feature = "python-bindings", pyo3::pyfunction)]
168167
pub fn keyfile_data_is_encrypted_nacl(keyfile_data: &[u8]) -> bool {
169168
keyfile_data.starts_with(b"$NACL")
170169
}
171170

172171
/// Returns true if the keyfile data is ansible encrypted.
173-
#[pyfunction]
172+
#[cfg_attr(feature = "python-bindings", pyo3::pyfunction)]
174173
pub fn keyfile_data_is_encrypted_ansible(keyfile_data: &[u8]) -> bool {
175174
keyfile_data.starts_with(b"$ANSIBLE_VAULT")
176175
}
177176

178177
/// Returns true if the keyfile data is legacy encrypted.
179-
#[pyfunction]
178+
#[cfg_attr(feature = "python-bindings", pyo3::pyfunction)]
180179
pub fn keyfile_data_is_encrypted_legacy(keyfile_data: &[u8]) -> bool {
181180
keyfile_data.starts_with(b"gAAAAA")
182181
}
183182

184183
/// Returns `true` if the keyfile data is encrypted.
185-
#[pyfunction]
184+
#[cfg_attr(feature = "python-bindings", pyo3::pyfunction)]
186185
pub fn keyfile_data_is_encrypted(keyfile_data: &[u8]) -> bool {
187186
let nacl = keyfile_data_is_encrypted_nacl(keyfile_data);
188187
let ansible = keyfile_data_is_encrypted_ansible(keyfile_data);
@@ -191,7 +190,7 @@ pub fn keyfile_data_is_encrypted(keyfile_data: &[u8]) -> bool {
191190
}
192191

193192
/// Returns type of encryption method as a string.
194-
#[pyfunction]
193+
#[cfg_attr(feature = "python-bindings", pyo3::pyfunction)]
195194
pub fn keyfile_data_encryption_method(keyfile_data: &[u8]) -> String {
196195
if keyfile_data_is_encrypted_nacl(keyfile_data) {
197196
"NaCl"

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ mod constants;
33
mod errors;
44
mod keyfile;
55
mod keypair;
6+
#[cfg(feature = "python-bindings")]
67
mod python_bindings;
78
mod utils;
89
mod wallet;

src/utils.rs

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use pyo3::pyfunction;
21
use sp_core::crypto::{AccountId32, Ss58Codec};
32
use std::str;
43

@@ -21,7 +20,7 @@ pub fn get_ss58_format(ss58_address: &str) -> Result<u16, &'static str> {
2120
///
2221
/// Returns:
2322
/// True if the address is a valid ss58 address for Bittensor, False otherwise.
24-
#[pyfunction]
23+
#[cfg_attr(feature = "python-bindings", pyo3::pyfunction)]
2524
pub fn is_valid_ss58_address(address: &str) -> bool {
2625
if address.is_empty() {
2726
// Possibly there could be a debug log, but not a print
@@ -81,7 +80,7 @@ pub fn are_bytes_valid_ed25519_pubkey(public_key: &[u8]) -> bool {
8180
///
8281
/// Returns:
8382
/// True if the address is a valid destination address, False otherwise.
84-
#[pyfunction]
83+
#[cfg_attr(feature = "python-bindings", pyo3::pyfunction)]
8584
pub fn is_valid_bittensor_address_or_public_key(address: &str) -> bool {
8685
if address.starts_with("0x") {
8786
// Convert hex string to bytes
@@ -104,20 +103,18 @@ pub fn print(s: String) {
104103

105104
#[cfg(feature = "python-bindings")]
106105
pub fn print(s: String) {
107-
pyo3::Python::with_gil(|py| {
108-
let locals = PyDict::new_bound(py);
109-
locals.set_item("s", s).unwrap();
110-
py.run_bound(
111-
r#"
112-
import sys
113-
print(s, end='')
114-
sys.stdout.flush()
115-
"#,
116-
None,
117-
Some(&locals),
118-
)
119-
.unwrap();
106+
use pyo3::prelude::*;
107+
let result = Python::attach(|py| -> PyResult<()> {
108+
let stdout = py.import("sys")?.getattr("stdout")?;
109+
stdout.call_method1("write", (s,))?;
110+
stdout.call_method0("flush")?;
111+
Ok(())
120112
});
113+
if cfg!(debug_assertions) {
114+
if let Err(e) = result {
115+
eprintln!("Python print failed: {e}");
116+
}
117+
}
121118
}
122119

123120
/// Prompts the user and returns the response, if any.

src/wallet.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use colored::Colorize;
2-
use pyo3::pyfunction;
32
use std::path::PathBuf;
43
use std::{env, fmt};
54

@@ -11,7 +10,7 @@ use crate::keypair::Keypair;
1110
use crate::utils::{self, is_valid_bittensor_address_or_public_key};
1211

1312
/// Display the mnemonic and a warning message to keep the mnemonic safe.
14-
#[pyfunction]
13+
#[cfg_attr(feature = "python-bindings", pyo3::pyfunction)]
1514
pub fn display_mnemonic_msg(mnemonic: String, key_type: &str) {
1615
utils::print(format!("{}", "\nIMPORTANT: Store this mnemonic in a secure (preferable offline place), as anyone who has possession of this mnemonic can use it to regenerate the key and access your tokens.\n".red()));
1716

0 commit comments

Comments
 (0)