unitforge 0.3.12__tar.gz → 0.3.14__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 (74) hide show
  1. {unitforge-0.3.12 → unitforge-0.3.14}/.gitignore +3 -1
  2. {unitforge-0.3.12 → unitforge-0.3.14}/Cargo.lock +2 -2
  3. {unitforge-0.3.12 → unitforge-0.3.14}/Cargo.toml +2 -2
  4. {unitforge-0.3.12 → unitforge-0.3.14}/PKG-INFO +1 -1
  5. {unitforge-0.3.12 → unitforge-0.3.14}/pyproject.toml +4 -0
  6. unitforge-0.3.14/python/unitforge/__init__.py +4 -0
  7. {unitforge-0.3.12 → unitforge-0.3.14}/unitforge_macros/Cargo.toml +1 -1
  8. {unitforge-0.3.12 → unitforge-0.3.14}/unitforge_macros/src/lib.rs +76 -5
  9. unitforge-0.3.12/python/unitforge/__init__.pyi +0 -1744
  10. unitforge-0.3.12/python/unitforge/py.typed +0 -0
  11. {unitforge-0.3.12 → unitforge-0.3.14}/.gitlab-ci.yml +0 -0
  12. {unitforge-0.3.12 → unitforge-0.3.14}/Readme.md +0 -0
  13. {unitforge-0.3.12 → unitforge-0.3.14}/Readme_py.md +0 -0
  14. {unitforge-0.3.12 → unitforge-0.3.14}/scripts/generate_python_stubs.py +0 -0
  15. {unitforge-0.3.12 → unitforge-0.3.14}/src/impl_macros.rs +0 -0
  16. {unitforge-0.3.12 → unitforge-0.3.14}/src/lib.rs +0 -0
  17. {unitforge-0.3.12 → unitforge-0.3.14}/src/prelude.rs +0 -0
  18. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/acceleration.rs +0 -0
  19. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/angle.rs +0 -0
  20. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/angular_acceleration.rs +0 -0
  21. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/angular_velocity.rs +0 -0
  22. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/area.rs +0 -0
  23. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/area_of_moment.rs +0 -0
  24. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/charge.rs +0 -0
  25. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/compliance.rs +0 -0
  26. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/density.rs +0 -0
  27. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/distance.rs +0 -0
  28. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/force.rs +0 -0
  29. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/force_area.rs +0 -0
  30. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/force_distance.rs +0 -0
  31. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/force_div_distance_power_four.rs +0 -0
  32. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/force_per_volume.rs +0 -0
  33. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/force_stress.rs +0 -0
  34. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/force_volume.rs +0 -0
  35. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/inverse_area.rs +0 -0
  36. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/inverse_distance.rs +0 -0
  37. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/inverse_stress.rs +0 -0
  38. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/mass.rs +0 -0
  39. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/mass_div_time_squared_volume.rs +0 -0
  40. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/mass_per_distance.rs +0 -0
  41. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/rotational_stiffness.rs +0 -0
  42. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/stiffness.rs +0 -0
  43. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/strain.rs +0 -0
  44. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/stress.rs +0 -0
  45. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/stress_squared.rs +0 -0
  46. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/time.rs +0 -0
  47. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/velocity.rs +0 -0
  48. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/velocity_squared.rs +0 -0
  49. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/voltage.rs +0 -0
  50. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities/volume.rs +0 -0
  51. {unitforge-0.3.12 → unitforge-0.3.14}/src/quantities.template.rs +0 -0
  52. {unitforge-0.3.12 → unitforge-0.3.14}/src/relations.rs +0 -0
  53. {unitforge-0.3.12 → unitforge-0.3.14}/src/small_linalg/bindings/matrix3_py.template.rs +0 -0
  54. {unitforge-0.3.12 → unitforge-0.3.14}/src/small_linalg/bindings/vector3_py.template.rs +0 -0
  55. {unitforge-0.3.12 → unitforge-0.3.14}/src/small_linalg/matrix2.rs +0 -0
  56. {unitforge-0.3.12 → unitforge-0.3.14}/src/small_linalg/matrix2x3.rs +0 -0
  57. {unitforge-0.3.12 → unitforge-0.3.14}/src/small_linalg/matrix3.rs +0 -0
  58. {unitforge-0.3.12 → unitforge-0.3.14}/src/small_linalg/matrix3x2.rs +0 -0
  59. {unitforge-0.3.12 → unitforge-0.3.14}/src/small_linalg/vector2.rs +0 -0
  60. {unitforge-0.3.12 → unitforge-0.3.14}/src/small_linalg/vector3.rs +0 -0
  61. {unitforge-0.3.12 → unitforge-0.3.14}/src/tests/quantity_unit_tests.rs +0 -0
  62. {unitforge-0.3.12 → unitforge-0.3.14}/src/tests/serde_tests.rs +0 -0
  63. {unitforge-0.3.12 → unitforge-0.3.14}/tests/matrix2.rs +0 -0
  64. {unitforge-0.3.12 → unitforge-0.3.14}/tests/matrix2x3.rs +0 -0
  65. {unitforge-0.3.12 → unitforge-0.3.14}/tests/matrix3.rs +0 -0
  66. {unitforge-0.3.12 → unitforge-0.3.14}/tests/matrix3x2.rs +0 -0
  67. {unitforge-0.3.12 → unitforge-0.3.14}/tests/ndarray_dot.rs +0 -0
  68. {unitforge-0.3.12 → unitforge-0.3.14}/tests/quantities.rs +0 -0
  69. {unitforge-0.3.12 → unitforge-0.3.14}/tests/small_linalg_interfaces.rs +0 -0
  70. {unitforge-0.3.12 → unitforge-0.3.14}/tests/test_quantities.py +0 -0
  71. {unitforge-0.3.12 → unitforge-0.3.14}/tests/test_small_linalg.py +0 -0
  72. {unitforge-0.3.12 → unitforge-0.3.14}/tests/typecheck/mypy_smoke.py +0 -0
  73. {unitforge-0.3.12 → unitforge-0.3.14}/tests/vector2.rs +0 -0
  74. {unitforge-0.3.12 → unitforge-0.3.14}/tests/vector3.rs +0 -0
@@ -1,7 +1,9 @@
1
1
  debug/
2
2
  target/
3
3
  dist/
4
- python/
4
+ python/unitforge/__init__.pyi
5
+ python/unitforge/py.typed
6
+ python/unitforge/unitforge*
5
7
  **/*.rs.bk
6
8
  .idea/
7
9
  .gitlab-ci-local/
@@ -369,7 +369,7 @@ checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3"
369
369
 
370
370
  [[package]]
371
371
  name = "unitforge"
372
- version = "0.3.12"
372
+ version = "0.3.14"
373
373
  dependencies = [
374
374
  "ndarray",
375
375
  "num-traits",
@@ -384,7 +384,7 @@ dependencies = [
384
384
 
385
385
  [[package]]
386
386
  name = "unitforge_macros"
387
- version = "0.3.12"
387
+ version = "0.3.14"
388
388
  dependencies = [
389
389
  "regex",
390
390
  ]
@@ -4,7 +4,7 @@ crate-type = ["cdylib", "rlib"]
4
4
 
5
5
  [package]
6
6
  name = "unitforge"
7
- version = "0.3.12"
7
+ version = "0.3.14"
8
8
  edition = "2021"
9
9
  authors = ["Dr.Q team <info@askdrq.com>", "Henrik Stromberg <henrik@askdrq.com>"]
10
10
  description = "A library for unit and quantity consistent computations in Rust"
@@ -23,7 +23,7 @@ pyo3 = { version = "0.26.0", features = ["extension-module", "auto-initialize",
23
23
  numpy = { version = "0.26.0", optional = true }
24
24
  strum = { version = "0.27.2", optional = true }
25
25
  strum_macros = { version = "0.27.2", optional = true }
26
- unitforge_macros = { version = "0.3.10", path = "unitforge_macros" }
26
+ unitforge_macros = { version = "0.3.14", path = "unitforge_macros" }
27
27
 
28
28
  [features]
29
29
  serde = ["dep:serde", "dep:serde_json", "ndarray/serde"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: unitforge
3
- Version: 0.3.12
3
+ Version: 0.3.14
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Rust
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -34,3 +34,7 @@ bindings = "pyo3"
34
34
  features = ["pyo3"]
35
35
  python-source = "python"
36
36
  module-name = "unitforge.unitforge"
37
+ include = [
38
+ "unitforge/__init__.pyi",
39
+ "unitforge/py.typed",
40
+ ]
@@ -0,0 +1,4 @@
1
+ from .unitforge import * # noqa: F401,F403
2
+ from . import unitforge as _ext
3
+ _UNITFORGE_API = _ext._UNITFORGE_API
4
+ del _ext
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "unitforge_macros"
3
- version = "0.3.12"
3
+ version = "0.3.14"
4
4
  edition = "2021"
5
5
  authors = ["Dr.Q team <info@askdrq.com>", "Henrik Stromberg <henrik@askdrq.com>"]
6
6
  description = "Proc macros for generating units, quantities, and Python bindings in unitforge"
@@ -244,6 +244,75 @@ fn parse_unit_variants(files: &[String], unit_name: &str) -> Result<Vec<String>,
244
244
  Err(format!("Enum {unit_name} not found in quantity source files"))
245
245
  }
246
246
 
247
+ fn fnv1a32(input: &str) -> u32 {
248
+ const OFFSET_BASIS: u32 = 0x811C9DC5;
249
+ const FNV_PRIME: u32 = 0x01000193;
250
+
251
+ let mut hash = OFFSET_BASIS;
252
+ for byte in input.as_bytes() {
253
+ hash ^= *byte as u32;
254
+ hash = hash.wrapping_mul(FNV_PRIME);
255
+ }
256
+ hash
257
+ }
258
+
259
+ fn stable_non_zero_hash(namespace: &str, name: &str) -> u32 {
260
+ let key = format!("{namespace}:{name}");
261
+ let mut hash = fnv1a32(&key);
262
+ if hash == 0 {
263
+ hash = fnv1a32(&format!("{key}#"));
264
+ if hash == 0 {
265
+ hash = 1;
266
+ }
267
+ }
268
+ hash
269
+ }
270
+
271
+ fn stable_quantity_kind_id(quantity_name: &str) -> u32 {
272
+ stable_non_zero_hash("unitforge.quantity", quantity_name)
273
+ }
274
+
275
+ fn stable_unit_variant_id(unit_name: &str, variant_name: &str) -> i32 {
276
+ let hash = stable_non_zero_hash(
277
+ "unitforge.unit_variant",
278
+ &format!("{unit_name}.{variant_name}"),
279
+ );
280
+ (hash & 0x7FFF_FFFF) as i32
281
+ }
282
+
283
+ fn ensure_stable_id_collisions(
284
+ quantity_names: &[String],
285
+ unit_variants_by_name: &HashMap<String, Vec<String>>,
286
+ ) -> Result<(), String> {
287
+ let mut quantity_ids: HashMap<u32, String> = HashMap::new();
288
+ for quantity_name in quantity_names {
289
+ let id = stable_quantity_kind_id(quantity_name);
290
+ if let Some(existing) = quantity_ids.insert(id, quantity_name.clone()) {
291
+ if existing != *quantity_name {
292
+ return Err(format!(
293
+ "Quantity kind id collision: '{existing}' and '{quantity_name}' both map to id {id}"
294
+ ));
295
+ }
296
+ }
297
+ }
298
+
299
+ for (unit_name, variants) in unit_variants_by_name {
300
+ let mut variant_ids: HashMap<i32, String> = HashMap::new();
301
+ for variant_name in variants {
302
+ let id = stable_unit_variant_id(unit_name, variant_name);
303
+ if let Some(existing) = variant_ids.insert(id, variant_name.clone()) {
304
+ if existing != *variant_name {
305
+ return Err(format!(
306
+ "Unit variant id collision in {unit_name}: '{existing}' and '{variant_name}' both map to id {id}"
307
+ ));
308
+ }
309
+ }
310
+ }
311
+ }
312
+
313
+ Ok(())
314
+ }
315
+
247
316
  fn write_quantity_code(
248
317
  template: &str,
249
318
  files: &[String],
@@ -283,6 +352,7 @@ fn write_quantity_code(
283
352
  let variants = parse_unit_variants(files, &unit_name)?;
284
353
  unit_variants_by_name.insert(unit_name, variants);
285
354
  }
355
+ ensure_stable_id_collisions(quantity_names, &unit_variants_by_name)?;
286
356
 
287
357
  let mul_macro_re = Regex::new(r"impl_mul!\(\s*(\w+),\s*(\w+),\s*(\w+)\)").unwrap();
288
358
  let div_macro_re = Regex::new(r"impl_div!\(\s*(\w+),\s*(\w+),\s*(\w+)\)").unwrap();
@@ -294,8 +364,8 @@ fn write_quantity_code(
294
364
  let mul_self_rel_re = Regex::new(r"impl_mul_relation_with_self!\(\s*(\w+),\s*(\w+)\)").unwrap();
295
365
 
296
366
  let mut first = true;
297
- for (index, struct_name) in quantity_names.iter().enumerate() {
298
- let quantity_kind_id = (index + 1) as u32;
367
+ for struct_name in quantity_names {
368
+ let quantity_kind_id = stable_quantity_kind_id(struct_name);
299
369
  let unit_name = format!("{struct_name}Unit");
300
370
  let unit_variant_list = unit_variants_by_name
301
371
  .get(&unit_name)
@@ -371,12 +441,13 @@ fn write_quantity_code(
371
441
 
372
442
  let mut variant_to_id_match = String::new();
373
443
  let mut id_to_variant_match = String::new();
374
- for (variant_index, variant_name) in unit_variant_list.iter().enumerate() {
444
+ for variant_name in unit_variant_list {
445
+ let variant_id = stable_unit_variant_id(&unit_name, variant_name);
375
446
  variant_to_id_match += &format!(
376
- " {struct_name}Unit::{variant_name} => {variant_index},\n"
447
+ " {struct_name}Unit::{variant_name} => {variant_id},\n"
377
448
  );
378
449
  id_to_variant_match += &format!(
379
- " {variant_index} => Some({struct_name}Unit::{variant_name}),\n"
450
+ " {variant_id} => Some({struct_name}Unit::{variant_name}),\n"
380
451
  );
381
452
  }
382
453
  unit_variant_id_impls += &format!(