nano-rspow-python 0.13.0__tar.gz → 0.16.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/Cargo.lock +12 -5
- {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/Cargo.toml +1 -1
- {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/PKG-INFO +15 -2
- {nano_rspow_python-0.13.0/nano-rspow-python → nano_rspow_python-0.16.0}/README.md +13 -0
- {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/Cargo.toml +1 -1
- {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/README.md +4 -1
- {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0/nano-rspow-python}/README.md +13 -0
- {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow-python/nano_rspow.pyi +8 -0
- {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow-python/src/lib.rs +117 -0
- {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/pyproject.toml +4 -1
- {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/benches/pow_benchmark.rs +0 -0
- {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/src/cpu.rs +0 -0
- {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/src/difficulty.rs +0 -0
- {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/src/lib.rs +0 -0
- {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/src/opencl_backend/mod.rs +0 -0
- {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/src/opencl_backend/pow.cl +0 -0
- {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/src/thresholds.rs +0 -0
- {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/src/types.rs +0 -0
- {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/src/wgpu_backend/mod.rs +0 -0
- {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/src/wgpu_backend/pow.wgsl +0 -0
- {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/src/wgpu_shared.rs +0 -0
- {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow-python/Cargo.toml +0 -0
- {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow-python/build.rs +0 -0
- {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow-python/tests/test_pow.py +0 -0
- {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow-python/uv.lock +0 -0
|
@@ -757,7 +757,7 @@ dependencies = [
|
|
|
757
757
|
|
|
758
758
|
[[package]]
|
|
759
759
|
name = "nano-rspow"
|
|
760
|
-
version = "0.
|
|
760
|
+
version = "0.16.0"
|
|
761
761
|
dependencies = [
|
|
762
762
|
"blake2b_simd",
|
|
763
763
|
"bytemuck",
|
|
@@ -773,7 +773,7 @@ dependencies = [
|
|
|
773
773
|
|
|
774
774
|
[[package]]
|
|
775
775
|
name = "nano-rspow-cli"
|
|
776
|
-
version = "0.
|
|
776
|
+
version = "0.16.0"
|
|
777
777
|
dependencies = [
|
|
778
778
|
"clap",
|
|
779
779
|
"hex",
|
|
@@ -783,9 +783,16 @@ dependencies = [
|
|
|
783
783
|
"tiny_http",
|
|
784
784
|
]
|
|
785
785
|
|
|
786
|
+
[[package]]
|
|
787
|
+
name = "nano-rspow-ffi"
|
|
788
|
+
version = "0.16.0"
|
|
789
|
+
dependencies = [
|
|
790
|
+
"nano-rspow",
|
|
791
|
+
]
|
|
792
|
+
|
|
786
793
|
[[package]]
|
|
787
794
|
name = "nano-rspow-node"
|
|
788
|
-
version = "0.
|
|
795
|
+
version = "0.16.0"
|
|
789
796
|
dependencies = [
|
|
790
797
|
"hex",
|
|
791
798
|
"nano-rspow",
|
|
@@ -797,7 +804,7 @@ dependencies = [
|
|
|
797
804
|
|
|
798
805
|
[[package]]
|
|
799
806
|
name = "nano-rspow-python"
|
|
800
|
-
version = "0.
|
|
807
|
+
version = "0.16.0"
|
|
801
808
|
dependencies = [
|
|
802
809
|
"hex",
|
|
803
810
|
"nano-rspow",
|
|
@@ -806,7 +813,7 @@ dependencies = [
|
|
|
806
813
|
|
|
807
814
|
[[package]]
|
|
808
815
|
name = "nano-rspow-web"
|
|
809
|
-
version = "0.
|
|
816
|
+
version = "0.16.0"
|
|
810
817
|
dependencies = [
|
|
811
818
|
"bytemuck",
|
|
812
819
|
"getrandom",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nano-rspow-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.16.0
|
|
4
4
|
Classifier: Programming Language :: Python :: 3
|
|
5
5
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
6
6
|
Classifier: Programming Language :: Python :: 3.9
|
|
@@ -13,7 +13,7 @@ Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
|
13
13
|
Classifier: Programming Language :: Rust
|
|
14
14
|
Classifier: Topic :: Security :: Cryptography
|
|
15
15
|
Summary: Hybrid CPU/GPU Nano (XNO) Proof of Work library — Python bindings.
|
|
16
|
-
Keywords: nano,xno,proof-of-work,blake2b
|
|
16
|
+
Keywords: nano,xno,nanocurrency,proof-of-work,blake2b
|
|
17
17
|
Author-email: Conny Brunnkvist <cbrunnkvist@gmail.com>
|
|
18
18
|
License-Expression: MIT
|
|
19
19
|
Requires-Python: >=3.9
|
|
@@ -32,6 +32,19 @@ Native Nano (XNO) proof-of-work bindings for Python. The extension selects an av
|
|
|
32
32
|
pip install nano-rspow-python
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
+
The package also installs a minimal streaming executable named
|
|
36
|
+
`nano-rspow-python`. It accepts no options except `--help` and uses the same
|
|
37
|
+
line protocol as `nano-rspow generate --stream`:
|
|
38
|
+
|
|
39
|
+
```text
|
|
40
|
+
<hash_hex>[:0x<threshold_hex>]
|
|
41
|
+
<hash_hex>:0x<threshold_hex>:<work_hex>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`nano-rspow` remains the full-featured CLI provided by the Rust
|
|
45
|
+
`nano-rspow-cli` crate; this Python package intentionally exposes only the
|
|
46
|
+
`nano-rspow-python` entrypoint.
|
|
47
|
+
|
|
35
48
|
## Usage
|
|
36
49
|
|
|
37
50
|
```python
|
|
@@ -8,6 +8,19 @@ Native Nano (XNO) proof-of-work bindings for Python. The extension selects an av
|
|
|
8
8
|
pip install nano-rspow-python
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
The package also installs a minimal streaming executable named
|
|
12
|
+
`nano-rspow-python`. It accepts no options except `--help` and uses the same
|
|
13
|
+
line protocol as `nano-rspow generate --stream`:
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
<hash_hex>[:0x<threshold_hex>]
|
|
17
|
+
<hash_hex>:0x<threshold_hex>:<work_hex>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`nano-rspow` remains the full-featured CLI provided by the Rust
|
|
21
|
+
`nano-rspow-cli` crate; this Python package intentionally exposes only the
|
|
22
|
+
`nano-rspow-python` entrypoint.
|
|
23
|
+
|
|
11
24
|
## Usage
|
|
12
25
|
|
|
13
26
|
```python
|
|
@@ -6,7 +6,7 @@ repository.workspace = true
|
|
|
6
6
|
version.workspace = true
|
|
7
7
|
readme = "README.md"
|
|
8
8
|
description = "Hybrid CPU/GPU Nano (XNO) Proof of Work library — Rust core, cross-platform."
|
|
9
|
-
keywords = ["nano", "xno", "proof-of-work", "blake2b"
|
|
9
|
+
keywords = ["nano", "xno", "nanocurrency", "proof-of-work", "blake2b"]
|
|
10
10
|
categories = ["cryptography", "hardware-support"]
|
|
11
11
|
|
|
12
12
|
[features]
|
|
@@ -57,8 +57,9 @@ Below is the directory mapping for each target, along with their primary release
|
|
|
57
57
|
| **Rust (Core)** | [crate API documentation](nano-rspow/src/lib.rs) | [GitHub Releases](https://github.com/CasualSecurityInc/nano-rspow/releases) |
|
|
58
58
|
| **Node.js & TS** | [nano-rspow-node README](https://github.com/CasualSecurityInc/nano-rspow/blob/HEAD/nano-rspow-node/README.md) | [Public NPM package](https://www.npmjs.com/package/nano-rspow-node) |
|
|
59
59
|
| **Python** | [nano-rspow-python README](nano-rspow-python/README.md) | [PyPI (pip)](https://pypi.org/project/nano-rspow-python/) |
|
|
60
|
+
| **Go** | [nano-rspow-go README](nano-rspow-go/README.md) | Go module source checkout |
|
|
60
61
|
| **Web (WASM / WebGPU)** | [nano-rspow-web/README.md](nano-rspow-web/README.md) | [Public NPM package](https://www.npmjs.com/package/nano-rspow-web) + [🎛️ Demo](https://csi.ninzin.net/nano-rspow/) |
|
|
61
|
-
| **CLI Tool** | [nano-rspow-cli README](nano-rspow-cli/README.md) | [crates.io](https://crates.io/crates/nano-rspow-cli) · [GitHub Releases](https://github.com/CasualSecurityInc/nano-rspow/releases) |
|
|
62
|
+
| **CLI Tool** | [nano-rspow-cli README](nano-rspow-cli/README.md) | The only full-featured `nano-rspow` executable: [crates.io](https://crates.io/crates/nano-rspow-cli) · [GitHub Releases](https://github.com/CasualSecurityInc/nano-rspow/releases) |
|
|
62
63
|
|
|
63
64
|
---
|
|
64
65
|
|
|
@@ -70,7 +71,9 @@ This monorepo is organized into specialized workspaces to deliver native perform
|
|
|
70
71
|
.
|
|
71
72
|
├── .cargo/ # Target-specific build configurations and cargo aliases
|
|
72
73
|
├── nano-rspow/ # Core Rust library containing cryptographic Blake2b logic & backends
|
|
74
|
+
├── nano-rspow-ffi/ # C ABI used by the Go bindings
|
|
73
75
|
├── nano-rspow-cli/ # Standalone CLI binary for hardware benchmarking & generation
|
|
76
|
+
├── nano-rspow-go/ # Go module and nano-rspow-go streaming CLI
|
|
74
77
|
├── nano-rspow-node/ # High-performance Node.js & TypeScript native bindings (N-API)
|
|
75
78
|
├── nano-rspow-python/ # Native PyO3 bindings for Python environments
|
|
76
79
|
└── nano-rspow-web/ # Web/WASM target crate & self-contained HTML benchmarking dashboard
|
|
@@ -8,6 +8,19 @@ Native Nano (XNO) proof-of-work bindings for Python. The extension selects an av
|
|
|
8
8
|
pip install nano-rspow-python
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
The package also installs a minimal streaming executable named
|
|
12
|
+
`nano-rspow-python`. It accepts no options except `--help` and uses the same
|
|
13
|
+
line protocol as `nano-rspow generate --stream`:
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
<hash_hex>[:0x<threshold_hex>]
|
|
17
|
+
<hash_hex>:0x<threshold_hex>:<work_hex>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`nano-rspow` remains the full-featured CLI provided by the Rust
|
|
21
|
+
`nano-rspow-cli` crate; this Python package intentionally exposes only the
|
|
22
|
+
`nano-rspow-python` entrypoint.
|
|
23
|
+
|
|
11
24
|
## Usage
|
|
12
25
|
|
|
13
26
|
```python
|
|
@@ -63,6 +63,10 @@ def generate_work(hash_hex: str, work_type: WorkType) -> WorkResult:
|
|
|
63
63
|
"""
|
|
64
64
|
...
|
|
65
65
|
|
|
66
|
+
def generate_work_with_threshold(hash_hex: str, threshold_hex: str) -> WorkResult:
|
|
67
|
+
"""Generate valid Proof of Work for an arbitrary hexadecimal threshold."""
|
|
68
|
+
...
|
|
69
|
+
|
|
66
70
|
def validate_work(hash_hex: str, work_hex: str, work_type: WorkType) -> bool:
|
|
67
71
|
"""Validate a work nonce against a hash and threshold.
|
|
68
72
|
|
|
@@ -101,6 +105,10 @@ def backend_name() -> str:
|
|
|
101
105
|
"""
|
|
102
106
|
...
|
|
103
107
|
|
|
108
|
+
def cli_main() -> int:
|
|
109
|
+
"""Run the minimal line-buffered nano-rspow-python CLI."""
|
|
110
|
+
...
|
|
111
|
+
|
|
104
112
|
class thresholds:
|
|
105
113
|
"""Nano PoW threshold constants for all network epochs.
|
|
106
114
|
|
|
@@ -29,6 +29,7 @@ use pyo3::exceptions::PyValueError;
|
|
|
29
29
|
use pyo3::prelude::*;
|
|
30
30
|
|
|
31
31
|
use ::nano_rspow::{WorkGenerator, difficulty, thresholds};
|
|
32
|
+
use std::io::{BufRead, Write};
|
|
32
33
|
use std::sync::OnceLock;
|
|
33
34
|
|
|
34
35
|
// ---------------------------------------------------------------------------
|
|
@@ -187,6 +188,35 @@ fn generate_work(py: Python<'_>, hash_hex: &str, work_type: WorkType) -> PyResul
|
|
|
187
188
|
}
|
|
188
189
|
}
|
|
189
190
|
|
|
191
|
+
/// Generate valid Proof of Work for an arbitrary hexadecimal threshold.
|
|
192
|
+
#[pyfunction]
|
|
193
|
+
fn generate_work_with_threshold(
|
|
194
|
+
py: Python<'_>,
|
|
195
|
+
hash_hex: &str,
|
|
196
|
+
threshold_hex: &str,
|
|
197
|
+
) -> PyResult<WorkResult> {
|
|
198
|
+
let hash = parse_hash(hash_hex)?;
|
|
199
|
+
let threshold = u64::from_str_radix(
|
|
200
|
+
threshold_hex.trim().trim_start_matches("0x"),
|
|
201
|
+
16,
|
|
202
|
+
)
|
|
203
|
+
.map_err(|e| PyValueError::new_err(format!("Invalid threshold hex: {e}")))?;
|
|
204
|
+
let generator = get_generator();
|
|
205
|
+
|
|
206
|
+
let result = py.detach(move || generator.generate(&hash, threshold));
|
|
207
|
+
|
|
208
|
+
match result {
|
|
209
|
+
Some(r) => Ok(WorkResult {
|
|
210
|
+
nonce: r.nonce,
|
|
211
|
+
difficulty: r.difficulty,
|
|
212
|
+
threshold: r.threshold,
|
|
213
|
+
}),
|
|
214
|
+
None => Err(pyo3::exceptions::PyRuntimeError::new_err(
|
|
215
|
+
"Work generation failed or was cancelled",
|
|
216
|
+
)),
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
190
220
|
/// Validate a work nonce against a hash and threshold.
|
|
191
221
|
///
|
|
192
222
|
/// Args:
|
|
@@ -242,6 +272,91 @@ fn backend_name() -> &'static str {
|
|
|
242
272
|
get_generator().backend_name()
|
|
243
273
|
}
|
|
244
274
|
|
|
275
|
+
const CLI_HELP: &str = "nano-rspow-python generates Nano proof of work from stdin.\n\nUsage:\n nano-rspow-python [--help]\n\nWith no arguments, read one request per line and write one result per line.\nEmpty lines are ignored. The only accepted argument is --help.\n\nInput:\n <hash_hex>\n <hash_hex>:<threshold_hex>\n\nThe optional threshold must use a 0x prefix. Without one, the current\nepoch-2 send/change threshold is used.\n\nOutput:\n <hash_hex>:0x<threshold_hex>:<work_hex>\n";
|
|
276
|
+
|
|
277
|
+
fn parse_cli_request(line: &str) -> Result<(String, [u8; 32], u64), String> {
|
|
278
|
+
let parts: Vec<&str> = line.split(':').collect();
|
|
279
|
+
if parts.len() > 2 {
|
|
280
|
+
return Err("request must be <hash_hex> or <hash_hex>:<threshold_hex>".to_owned());
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
let hash_text = parts[0].trim().to_owned();
|
|
284
|
+
let hash = parse_hash(&hash_text).map_err(|error| error.to_string())?;
|
|
285
|
+
let threshold = if let Some(threshold_text) = parts.get(1).map(|part| part.trim()) {
|
|
286
|
+
if !threshold_text.starts_with("0x") {
|
|
287
|
+
return Err(format!(
|
|
288
|
+
"threshold {threshold_text:?} must start with 0x"
|
|
289
|
+
));
|
|
290
|
+
}
|
|
291
|
+
u64::from_str_radix(&threshold_text[2..], 16)
|
|
292
|
+
.map_err(|error| format!("invalid threshold {threshold_text:?}: {error}"))?
|
|
293
|
+
} else {
|
|
294
|
+
thresholds::EPOCH2_SEND
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
Ok((hash_text, hash, threshold))
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/// Run the minimal line-buffered CLI shipped as `nano-rspow-python`.
|
|
301
|
+
#[pyfunction]
|
|
302
|
+
fn cli_main(py: Python<'_>) -> PyResult<i32> {
|
|
303
|
+
let sys = py.import("sys")?;
|
|
304
|
+
let args: Vec<String> = sys
|
|
305
|
+
.getattr("argv")?
|
|
306
|
+
.extract::<Vec<String>>()?
|
|
307
|
+
.into_iter()
|
|
308
|
+
.skip(1)
|
|
309
|
+
.collect();
|
|
310
|
+
if args == ["--help"] {
|
|
311
|
+
print!("{CLI_HELP}");
|
|
312
|
+
return Ok(0);
|
|
313
|
+
}
|
|
314
|
+
if !args.is_empty() {
|
|
315
|
+
eprintln!("error: only --help is supported");
|
|
316
|
+
eprint!("{CLI_HELP}");
|
|
317
|
+
return Ok(2);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
let generator = get_generator();
|
|
321
|
+
let stdin = std::io::stdin();
|
|
322
|
+
let mut stdout = std::io::BufWriter::new(std::io::stdout());
|
|
323
|
+
for line_result in stdin.lock().lines() {
|
|
324
|
+
let line = line_result.map_err(|error| {
|
|
325
|
+
pyo3::exceptions::PyRuntimeError::new_err(format!("Error reading input: {error}"))
|
|
326
|
+
})?;
|
|
327
|
+
let line = line.trim();
|
|
328
|
+
if line.is_empty() {
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
let (hash_text, hash, threshold) = match parse_cli_request(line) {
|
|
333
|
+
Ok(request) => request,
|
|
334
|
+
Err(error) => {
|
|
335
|
+
eprintln!("Error parsing request {line:?}: {error}");
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
let result = py.detach(move || generator.generate(&hash, threshold));
|
|
341
|
+
let Some(result) = result else {
|
|
342
|
+
eprintln!("Error generating work for {hash_text}: generation failed");
|
|
343
|
+
continue;
|
|
344
|
+
};
|
|
345
|
+
writeln!(
|
|
346
|
+
stdout,
|
|
347
|
+
"{hash_text}:0x{threshold:016x}:{:016x}",
|
|
348
|
+
result.nonce
|
|
349
|
+
)
|
|
350
|
+
.map_err(|error| {
|
|
351
|
+
pyo3::exceptions::PyRuntimeError::new_err(format!("Error writing result: {error}"))
|
|
352
|
+
})?;
|
|
353
|
+
stdout.flush().map_err(|error| {
|
|
354
|
+
pyo3::exceptions::PyRuntimeError::new_err(format!("Error flushing result: {error}"))
|
|
355
|
+
})?;
|
|
356
|
+
}
|
|
357
|
+
Ok(0)
|
|
358
|
+
}
|
|
359
|
+
|
|
245
360
|
// ---------------------------------------------------------------------------
|
|
246
361
|
// Threshold constants submodule
|
|
247
362
|
// ---------------------------------------------------------------------------
|
|
@@ -277,9 +392,11 @@ fn nano_rspow(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
|
|
277
392
|
m.add_class::<WorkType>()?;
|
|
278
393
|
m.add_class::<WorkResult>()?;
|
|
279
394
|
m.add_function(wrap_pyfunction!(generate_work, m)?)?;
|
|
395
|
+
m.add_function(wrap_pyfunction!(generate_work_with_threshold, m)?)?;
|
|
280
396
|
m.add_function(wrap_pyfunction!(validate_work, m)?)?;
|
|
281
397
|
m.add_function(wrap_pyfunction!(compute_difficulty, m)?)?;
|
|
282
398
|
m.add_function(wrap_pyfunction!(backend_name, m)?)?;
|
|
399
|
+
m.add_function(wrap_pyfunction!(cli_main, m)?)?;
|
|
283
400
|
register_thresholds(m)?;
|
|
284
401
|
Ok(())
|
|
285
402
|
}
|
|
@@ -12,7 +12,7 @@ license = "MIT"
|
|
|
12
12
|
authors = [
|
|
13
13
|
{ name = "Conny Brunnkvist", email = "cbrunnkvist@gmail.com" },
|
|
14
14
|
]
|
|
15
|
-
keywords = ["nano", "xno", "proof-of-work", "blake2b"
|
|
15
|
+
keywords = ["nano", "xno", "nanocurrency", "proof-of-work", "blake2b"]
|
|
16
16
|
classifiers = [
|
|
17
17
|
"Programming Language :: Python :: 3",
|
|
18
18
|
"Programming Language :: Python :: 3 :: Only",
|
|
@@ -32,6 +32,9 @@ Homepage = "https://github.com/CasualSecurityInc/nano-rspow"
|
|
|
32
32
|
Repository = "https://github.com/CasualSecurityInc/nano-rspow"
|
|
33
33
|
Issues = "https://github.com/CasualSecurityInc/nano-rspow/issues"
|
|
34
34
|
|
|
35
|
+
[project.scripts]
|
|
36
|
+
nano-rspow-python = "nano_rspow:cli_main"
|
|
37
|
+
|
|
35
38
|
[dependency-groups]
|
|
36
39
|
test = [
|
|
37
40
|
"maturin>=1.5",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|