python-aaronia 0.13.0__tar.gz → 0.13.1__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.
Files changed (95) hide show
  1. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/CHANGELOG.md +10 -0
  2. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/Cargo.lock +2 -2
  3. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/Cargo.toml +1 -1
  4. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/PKG-INFO +1 -1
  5. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/docs/SDKSPEC.md +8 -0
  6. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/python-aaronia/Cargo.toml +1 -1
  7. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/src/native_sdk.rs +42 -0
  8. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/src/native_sdk_lifecycle_tests.rs +70 -5
  9. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/tests/spec_coverage.rs +12 -0
  10. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/.cargo/config.toml +0 -0
  11. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/.gitattributes +0 -0
  12. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/.gitignore +0 -0
  13. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/CONTRIBUTING.md +0 -0
  14. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/DESIGN.md +0 -0
  15. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/LICENSE +0 -0
  16. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/PLUGINS.md +0 -0
  17. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/README.md +0 -0
  18. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/benches/decompress_block.rs +0 -0
  19. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/benches/deinterleave_dual_iq.rs +0 -0
  20. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/benches/parse_int16_packet.rs +0 -0
  21. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/benches/rtsa_open_and_read.rs +0 -0
  22. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/deny.toml +0 -0
  23. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/docs/APPS.md +0 -0
  24. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/docs/FILESPEC.md +0 -0
  25. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/docs/HTTPSPEC.md +0 -0
  26. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/docs/NATIVE_SDK_COMPATIBILITY.md +0 -0
  27. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/docs/QUICKSTART.md +0 -0
  28. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/docs/SYNC.md +0 -0
  29. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/docs/USAGE.md +0 -0
  30. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/docs/VERIFICATION.md +0 -0
  31. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/examples/device_control.rs +0 -0
  32. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/examples/dump_metadata.rs +0 -0
  33. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/examples/http_iq_quickstart.rs +0 -0
  34. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/examples/native_sdk_basic.rs +0 -0
  35. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/examples/native_sdk_qualification.rs +0 -0
  36. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/examples/native_sdk_transmit.rs +0 -0
  37. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/examples/noaa_scanner.rs +0 -0
  38. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/examples/python_arrow_example.py +0 -0
  39. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/examples/read_rtsa_file.rs +0 -0
  40. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/examples/soapy_python_example.py +0 -0
  41. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/include/spectran.h +0 -0
  42. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/packaging/homebrew/README.md +0 -0
  43. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/packaging/homebrew/soapy-aaronia.rb +0 -0
  44. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/pyproject.toml +0 -0
  45. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/python-aaronia/README.md +0 -0
  46. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/python-aaronia/aaronia.pyi +0 -0
  47. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/python-aaronia/src/lib.rs +0 -0
  48. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/python-aaronia/test_basic.py +0 -0
  49. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/scripts/ci-local.sh +0 -0
  50. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/scripts/fake-rtsa-server.py +0 -0
  51. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/scripts/native-sdk-validate.ps1 +0 -0
  52. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/scripts/sdk-container-test.sh +0 -0
  53. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/scripts/validate-iq-live.py +0 -0
  54. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/soapy-aaronia/CMakeLists.txt +0 -0
  55. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/soapy-aaronia/README.md +0 -0
  56. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/soapy-aaronia/Registration.cpp +0 -0
  57. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/soapy-aaronia/SpectranSoapyDevice.cpp +0 -0
  58. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/soapy-aaronia/SpectranSoapyDevice.hpp +0 -0
  59. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/soapy-aaronia/packaging/install.ps1 +0 -0
  60. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/soapy-aaronia/packaging/install.sh +0 -0
  61. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/src/c_api.rs +0 -0
  62. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/src/capabilities.rs +0 -0
  63. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/src/decompression.rs +0 -0
  64. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/src/detection.rs +0 -0
  65. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/src/error.rs +0 -0
  66. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/src/file_source.rs +0 -0
  67. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/src/http_endpoints.rs +0 -0
  68. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/src/http_sink.rs +0 -0
  69. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/src/http_source.rs +0 -0
  70. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/src/http_streaming.rs +0 -0
  71. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/src/lib.rs +0 -0
  72. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/src/link_budget.rs +0 -0
  73. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/src/sdk_sink.rs +0 -0
  74. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/src/sdk_source.rs +0 -0
  75. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/src/seify_impl.rs +0 -0
  76. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/src/stream_break.rs +0 -0
  77. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/src/stream_geometry.rs +0 -0
  78. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/src/unified_sink.rs +0 -0
  79. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/src/unified_source.rs +0 -0
  80. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/src/utils.rs +0 -0
  81. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/tests/abi_drift.rs +0 -0
  82. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/tests/c_api_test.rs +0 -0
  83. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/tests/http_mock_test.rs +0 -0
  84. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/tests/http_resilience_test.rs +0 -0
  85. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/tests/http_sink_test.rs +0 -0
  86. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/tests/integration_test.rs +0 -0
  87. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/tests/live_smoke.rs +0 -0
  88. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/tests/native_sdk_live.rs +0 -0
  89. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/tests/native_sdk_load.rs +0 -0
  90. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/tests/properties.proptest-regressions +0 -0
  91. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/tests/properties.rs +0 -0
  92. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/tests/rtsa_negative_test.rs +0 -0
  93. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/tests/test_cw_mag.rs +0 -0
  94. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/tests/test_cw_meta.rs +0 -0
  95. {python_aaronia-0.13.0 → python_aaronia-0.13.1}/tests/wire_contract.rs +0 -0
@@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [v0.13.1] - 2026-10-08
8
+
9
+ ### Added
10
+ - `NativeSdkSource::configure_sweepsa_with_reference_level` applies an optional
11
+ reference level to native spectrum sweeps, backported from Specola's vendor
12
+ update. Explicit levels require valid SDK bounds and are checked before any
13
+ configuration write; unsupported/missing settings fail instead of being ignored.
14
+ The existing `SweepsaConfig` layout and `configure_sweepsa` API remain compatible.
15
+
16
+
7
17
  ## [v0.13.0] - 2026-10-08
8
18
 
9
19
  ### Added
@@ -3049,7 +3049,7 @@ dependencies = [
3049
3049
 
3050
3050
  [[package]]
3051
3051
  name = "python-aaronia"
3052
- version = "0.13.0"
3052
+ version = "0.13.1"
3053
3053
  dependencies = [
3054
3054
  "arrow",
3055
3055
  "num-complex",
@@ -3578,7 +3578,7 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
3578
3578
 
3579
3579
  [[package]]
3580
3580
  name = "sdr-aaronia-rs"
3581
- version = "0.13.0"
3581
+ version = "0.13.1"
3582
3582
  dependencies = [
3583
3583
  "anyhow",
3584
3584
  "bitflags 2.13.1",
@@ -2,7 +2,7 @@
2
2
  name = "sdr-aaronia-rs"
3
3
  description = "Unified Rust interface for Aaronia Spectran Spectrum Analyzers / SDRs, featuring Python bindings, a SoapySDR plugin, HTTP streaming, and native SDK support."
4
4
  license = "GPL-3.0-or-later"
5
- version = "0.13.0"
5
+ version = "0.13.1"
6
6
  edition = "2024"
7
7
  repository = "https://github.com/isaacbentley/sdr-aaronia-rs"
8
8
  readme = "README.md"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-aaronia
3
- Version: 0.13.0
3
+ Version: 0.13.1
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
@@ -6,6 +6,14 @@ The Aaronia Real-Time Spectrum Analyzer (RTSA) Vendor Software Development Kit (
6
6
 
7
7
  > **Status & attribution.** This document is a *community-compiled* reference, **not** an official Aaronia specification. It is assembled from Aaronia's official open-source sample code, public posts on the Aaronia V6 forum, vendor SDK headers, and empirical analysis. Where these disagree, the vendor's own materials are authoritative. See [Sources and Attribution](#sources-and-attribution) for the upstream, vendor-published references.
8
8
 
9
+ ## Sweep reference level (0.13.1)
10
+
11
+ Use `configure_sweepsa_with_reference_level(&config, Some(-50.0))` to apply a
12
+ reference level in dBm. `None` preserves the previous setting, as the existing
13
+ `configure_sweepsa` call does. Explicit levels are validated against SDK metadata
14
+ before any sweep geometry is changed. This additive method carries Specola's
15
+ vendor functionality without adding a field to the public `SweepsaConfig` struct.
16
+
9
17
  ## Current driver behavior (0.13)
10
18
 
11
19
  See [Native SDK compatibility and qualification](NATIVE_SDK_COMPATIBILITY.md)
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "python-aaronia"
3
- version = "0.13.0"
3
+ version = "0.13.1"
4
4
  edition = "2024"
5
5
  description = "Python bindings for sdr-aaronia-rs (Aaronia SPECTRAN V6 SDR source)"
6
6
  license = "GPL-3.0-or-later"
@@ -2205,7 +2205,21 @@ impl NativeSdkSource {
2205
2205
  /// > tolerance in [`Self::configure_iq_receiver`] — so verify the
2206
2206
  /// > resulting device state before relying on this in production.
2207
2207
  pub unsafe fn configure_sweepsa(&mut self, config: &SweepsaConfig) -> Result<()> {
2208
+ unsafe { self.configure_sweepsa_with_reference_level(config, None) }
2209
+ }
2210
+
2211
+ /// Configure a spectrum sweep with an optional reference level in dBm.
2212
+ /// Existing SweepsaConfig struct literals remain compatible. An explicit
2213
+ /// level requires ConfigInfo bounds and is validated before any writes.
2214
+ pub unsafe fn configure_sweepsa_with_reference_level(
2215
+ &mut self,
2216
+ config: &SweepsaConfig,
2217
+ reference_level_dbm: Option<f64>,
2218
+ ) -> Result<()> {
2208
2219
  unsafe {
2220
+ if reference_level_dbm.is_some_and(|level| !level.is_finite()) {
2221
+ return Err(Error::Config("reference level must be finite".into()));
2222
+ }
2209
2223
  let device = self
2210
2224
  .device
2211
2225
  .as_mut()
@@ -2213,6 +2227,29 @@ impl NativeSdkSource {
2213
2227
 
2214
2228
  let mut root = self.client.get_config_root(device)?;
2215
2229
 
2230
+ // Keep the validated node so a missing/unsupported explicit setting
2231
+ // cannot be silently ignored after changing the sweep geometry.
2232
+ let reference = if let Some(level) = reference_level_dbm {
2233
+ let mut node = self
2234
+ .client
2235
+ .find_config(device, &mut root, "main/reflevel")?;
2236
+ let info = self.client.get_config_info(device, &mut node)?;
2237
+ let bounds = crate::capabilities::ValueRange::new(
2238
+ info.min_value,
2239
+ info.max_value,
2240
+ info.step_value,
2241
+ )
2242
+ .ok_or_else(|| Error::Config("reference level bounds are unknown".into()))?;
2243
+ if !bounds.contains(level) {
2244
+ return Err(Error::Config(format!(
2245
+ "reference level {level} is outside {bounds:?}"
2246
+ )));
2247
+ }
2248
+ Some((node, level))
2249
+ } else {
2250
+ None
2251
+ };
2252
+
2216
2253
  if let Ok(mut config_node) =
2217
2254
  self.client.find_config(device, &mut root, "main/startfreq")
2218
2255
  {
@@ -2241,6 +2278,11 @@ impl NativeSdkSource {
2241
2278
  info!("Set sweepsa vbw to {} Hz", config.vbw);
2242
2279
  }
2243
2280
 
2281
+ if let Some((mut node, level)) = reference {
2282
+ self.client.set_config_float(device, &mut node, level)?;
2283
+ info!("Set sweepsa reference level to {} dBm", level);
2284
+ }
2285
+
2244
2286
  Ok(())
2245
2287
  }
2246
2288
  }
@@ -1,9 +1,10 @@
1
1
  //! SDK lifecycle fault injection. No Aaronia installation or USB device.
2
2
  use super::*;
3
- use std::cell::RefCell;
3
+ use std::cell::{Cell, RefCell};
4
4
  thread_local! {
5
5
  static CALLS: RefCell<Vec<&'static str>> = const { RefCell::new(Vec::new()) };
6
6
  static FAIL: RefCell<Vec<&'static str>> = const { RefCell::new(Vec::new()) };
7
+ static CONFIG_AVAILABLE: Cell<bool> = const { Cell::new(false) };
7
8
  }
8
9
  fn call(name: &'static str) -> u32 {
9
10
  CALLS.with(|calls| calls.borrow_mut().push(name));
@@ -14,6 +15,7 @@ fn call(name: &'static str) -> u32 {
14
15
  }
15
16
  }
16
17
  fn reset(fail: &[&'static str]) {
18
+ CONFIG_AVAILABLE.with(|available| available.set(false));
17
19
  CALLS.with(|calls| calls.borrow_mut().clear());
18
20
  FAIL.with(|failed| *failed.borrow_mut() = fail.to_vec());
19
21
  }
@@ -88,7 +90,14 @@ unsafe extern "C" fn mock_config_root(
88
90
  _device: *mut AARTSAAPI_Device,
89
91
  _config: *mut AARTSAAPI_Config,
90
92
  ) -> u32 {
91
- AARTSAAPI_ERROR_NOT_FOUND
93
+ if CONFIG_AVAILABLE.with(Cell::get) {
94
+ unsafe {
95
+ (*_config).d = std::ptr::dangling_mut::<u8>().cast();
96
+ }
97
+ AARTSAAPI_OK
98
+ } else {
99
+ AARTSAAPI_ERROR_NOT_FOUND
100
+ }
92
101
  }
93
102
  unsafe extern "C" fn mock_config_health(
94
103
  _device: *mut AARTSAAPI_Device,
@@ -123,14 +132,21 @@ unsafe extern "C" fn mock_config_find(
123
132
  _config: *mut AARTSAAPI_Config,
124
133
  _path: *const WideChar,
125
134
  ) -> u32 {
126
- AARTSAAPI_ERROR_NOT_FOUND
135
+ if CONFIG_AVAILABLE.with(Cell::get) {
136
+ unsafe {
137
+ (*_config).d = std::ptr::dangling_mut::<u8>().cast();
138
+ }
139
+ AARTSAAPI_OK
140
+ } else {
141
+ AARTSAAPI_ERROR_NOT_FOUND
142
+ }
127
143
  }
128
144
  unsafe extern "C" fn mock_config_set_float(
129
145
  _device: *mut AARTSAAPI_Device,
130
146
  _config: *mut AARTSAAPI_Config,
131
147
  _value: f64,
132
148
  ) -> u32 {
133
- AARTSAAPI_ERROR_NOT_FOUND
149
+ call("config_write")
134
150
  }
135
151
  unsafe extern "C" fn mock_config_set_string(
136
152
  _device: *mut AARTSAAPI_Device,
@@ -159,7 +175,15 @@ unsafe extern "C" fn mock_config_get_info(
159
175
  _config: *mut AARTSAAPI_Config,
160
176
  _info: *mut AARTSAAPI_ConfigInfo,
161
177
  ) -> u32 {
162
- AARTSAAPI_ERROR_NOT_FOUND
178
+ if !CONFIG_AVAILABLE.with(Cell::get) {
179
+ return AARTSAAPI_ERROR_NOT_FOUND;
180
+ }
181
+ unsafe {
182
+ (*_info).min_value = -55.0;
183
+ (*_info).max_value = 23.0;
184
+ (*_info).step_value = 0.5;
185
+ }
186
+ AARTSAAPI_OK
163
187
  }
164
188
  unsafe extern "C" fn mock_config_get_float(
165
189
  _device: *mut AARTSAAPI_Device,
@@ -372,3 +396,44 @@ fn sdk_shutdown_waits_for_the_last_initialized_client() {
372
396
  }
373
397
  assert_eq!(calls(), vec!["init_with_path", "shutdown"]);
374
398
  }
399
+
400
+ #[test]
401
+ fn sweep_reference_level_is_checked_before_any_write() {
402
+ for level in [f64::NAN, f64::INFINITY, -56.0, 24.0] {
403
+ reset(&[]);
404
+ CONFIG_AVAILABLE.with(|available| available.set(true));
405
+ let mut source = source(false, false);
406
+ assert!(
407
+ unsafe {
408
+ source.configure_sweepsa_with_reference_level(&Default::default(), Some(level))
409
+ }
410
+ .is_err()
411
+ );
412
+ assert!(!calls().contains(&"config_write"));
413
+ }
414
+ reset(&[]);
415
+ CONFIG_AVAILABLE.with(|available| available.set(true));
416
+ let mut source = source(false, false);
417
+ unsafe {
418
+ source
419
+ .configure_sweepsa_with_reference_level(&Default::default(), Some(-50.0))
420
+ .unwrap();
421
+ }
422
+ assert_eq!(
423
+ calls()
424
+ .iter()
425
+ .filter(|&&call| call == "config_write")
426
+ .count(),
427
+ 5
428
+ );
429
+ }
430
+ #[test]
431
+ fn missing_explicit_sweep_reference_metadata_fails_before_writes() {
432
+ reset(&[]);
433
+ let mut source = source(false, false);
434
+ assert!(
435
+ unsafe { source.configure_sweepsa_with_reference_level(&Default::default(), Some(-50.0)) }
436
+ .is_err()
437
+ );
438
+ assert!(!calls().contains(&"config_write"));
439
+ }
@@ -38,6 +38,18 @@ struct InvariantRow {
38
38
  }
39
39
 
40
40
  const ENFORCED: &[InvariantRow] = &[
41
+ InvariantRow {
42
+ area: Area::Sdk,
43
+ invariant: "explicit sweep reference levels are finite and bounded before any write",
44
+ test_fn: "sweep_reference_level_is_checked_before_any_write",
45
+ test_file: "src/native_sdk_lifecycle_tests.rs",
46
+ },
47
+ InvariantRow {
48
+ area: Area::Sdk,
49
+ invariant: "missing explicit sweep reference metadata fails before geometry writes",
50
+ test_fn: "missing_explicit_sweep_reference_metadata_fails_before_writes",
51
+ test_file: "src/native_sdk_lifecycle_tests.rs",
52
+ },
41
53
  InvariantRow {
42
54
  area: Area::Sdk,
43
55
  invariant: "Teardown attempts stop, disconnect, close; errors are not swallowed",
File without changes