gitronics 0.5.7__tar.gz → 0.5.9__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 (59) hide show
  1. gitronics-0.5.9/.vscode/settings.json +4 -0
  2. {gitronics-0.5.7 → gitronics-0.5.9}/Cargo.lock +1 -1
  3. {gitronics-0.5.7 → gitronics-0.5.9}/Cargo.toml +1 -1
  4. {gitronics-0.5.7 → gitronics-0.5.9}/PKG-INFO +1 -1
  5. {gitronics-0.5.7 → gitronics-0.5.9}/docs/usage/build.md +20 -0
  6. {gitronics-0.5.7 → gitronics-0.5.9}/python/gitronics/__init__.py +2 -1
  7. gitronics-0.5.9/python/gitronics/__main__.py +3 -0
  8. gitronics-0.5.9/python/gitronics/gitronics.pyi +45 -0
  9. gitronics-0.5.9/python/tests/test_build_model.py +30 -0
  10. {gitronics-0.5.7 → gitronics-0.5.9}/src/build_model.rs +1 -0
  11. {gitronics-0.5.7 → gitronics-0.5.9}/src/model_config.rs +2 -1
  12. {gitronics-0.5.7 → gitronics-0.5.9}/src/project_manager/load_metadata.rs +2 -1
  13. gitronics-0.5.9/src/python.rs +31 -0
  14. {gitronics-0.5.7 → gitronics-0.5.9}/src/utils.rs +16 -0
  15. gitronics-0.5.7/src/python.rs +0 -16
  16. {gitronics-0.5.7 → gitronics-0.5.9}/.github/workflows/ci.yml +0 -0
  17. {gitronics-0.5.7 → gitronics-0.5.9}/.github/workflows/docs.yml +0 -0
  18. {gitronics-0.5.7 → gitronics-0.5.9}/.github/workflows/release.yml +0 -0
  19. {gitronics-0.5.7 → gitronics-0.5.9}/.gitignore +0 -0
  20. {gitronics-0.5.7 → gitronics-0.5.9}/LICENSE +0 -0
  21. {gitronics-0.5.7 → gitronics-0.5.9}/README.md +0 -0
  22. {gitronics-0.5.7 → gitronics-0.5.9}/docs/assets/logo.png +0 -0
  23. {gitronics-0.5.7 → gitronics-0.5.9}/docs/best-practices.md +0 -0
  24. {gitronics-0.5.7 → gitronics-0.5.9}/docs/changelog.md +0 -0
  25. {gitronics-0.5.7 → gitronics-0.5.9}/docs/examples.md +0 -0
  26. {gitronics-0.5.7 → gitronics-0.5.9}/docs/getting-started.md +0 -0
  27. {gitronics-0.5.7 → gitronics-0.5.9}/docs/index.md +0 -0
  28. {gitronics-0.5.7 → gitronics-0.5.9}/docs/installation.md +0 -0
  29. {gitronics-0.5.7 → gitronics-0.5.9}/docs/requirements.txt +0 -0
  30. {gitronics-0.5.7 → gitronics-0.5.9}/docs/usage/configuration.md +0 -0
  31. {gitronics-0.5.7 → gitronics-0.5.9}/docs/usage/migrate.md +0 -0
  32. {gitronics-0.5.7 → gitronics-0.5.9}/example_project/assessment_specific/filler_model_3.mcnp +0 -0
  33. {gitronics-0.5.7 → gitronics-0.5.9}/example_project/assessment_specific/filler_model_3.metadata +0 -0
  34. {gitronics-0.5.7 → gitronics-0.5.9}/example_project/assessment_specific/small_override.yaml +0 -0
  35. {gitronics-0.5.7 → gitronics-0.5.9}/example_project/configurations/valid_configuration.yaml +0 -0
  36. {gitronics-0.5.7 → gitronics-0.5.9}/example_project/output/.gitignore +0 -0
  37. {gitronics-0.5.7 → gitronics-0.5.9}/example_project/reference_model/data_cards/fine_mesh.tally +0 -0
  38. {gitronics-0.5.7 → gitronics-0.5.9}/example_project/reference_model/data_cards/materials.mat +0 -0
  39. {gitronics-0.5.7 → gitronics-0.5.9}/example_project/reference_model/data_cards/my_transform.transform +0 -0
  40. {gitronics-0.5.7 → gitronics-0.5.9}/example_project/reference_model/data_cards/volumetric_source.source +0 -0
  41. {gitronics-0.5.7 → gitronics-0.5.9}/example_project/reference_model/envelope_structure.mcnp +0 -0
  42. {gitronics-0.5.7 → gitronics-0.5.9}/example_project/reference_model/envelope_structure.metadata +0 -0
  43. {gitronics-0.5.7 → gitronics-0.5.9}/example_project/reference_model/filler_models/filler_model_1.mcnp +0 -0
  44. {gitronics-0.5.7 → gitronics-0.5.9}/example_project/reference_model/filler_models/filler_model_1.metadata +0 -0
  45. {gitronics-0.5.7 → gitronics-0.5.9}/example_project/reference_model/filler_models/filler_model_2.mcnp +0 -0
  46. {gitronics-0.5.7 → gitronics-0.5.9}/example_project/reference_model/filler_models/filler_model_2.metadata +0 -0
  47. {gitronics-0.5.7 → gitronics-0.5.9}/mkdocs.yml +0 -0
  48. {gitronics-0.5.7 → gitronics-0.5.9}/pyproject.toml +0 -0
  49. {gitronics-0.5.7 → gitronics-0.5.9}/python/tests/test_cli_works.py +0 -0
  50. {gitronics-0.5.7 → gitronics-0.5.9}/resources/simple_model.mcnp +0 -0
  51. {gitronics-0.5.7 → gitronics-0.5.9}/src/cli.rs +0 -0
  52. {gitronics-0.5.7 → gitronics-0.5.9}/src/lib.rs +0 -0
  53. {gitronics-0.5.7 → gitronics-0.5.9}/src/main.rs +0 -0
  54. {gitronics-0.5.7 → gitronics-0.5.9}/src/migrate_model.rs +0 -0
  55. {gitronics-0.5.7 → gitronics-0.5.9}/src/project_manager/load_model_config.rs +0 -0
  56. {gitronics-0.5.7 → gitronics-0.5.9}/src/project_manager/load_project_files.rs +0 -0
  57. {gitronics-0.5.7 → gitronics-0.5.9}/src/project_manager.rs +0 -0
  58. {gitronics-0.5.7 → gitronics-0.5.9}/src/types.rs +0 -0
  59. {gitronics-0.5.7 → gitronics-0.5.9}/tests/test_example_project.rs +0 -0
@@ -0,0 +1,4 @@
1
+ {
2
+ "python-envs.defaultEnvManager": "ms-python.python:conda",
3
+ "python-envs.defaultPackageManager": "ms-python.python:conda"
4
+ }
@@ -390,7 +390,7 @@ dependencies = [
390
390
 
391
391
  [[package]]
392
392
  name = "gitronics"
393
- version = "0.5.7"
393
+ version = "0.5.9"
394
394
  dependencies = [
395
395
  "chrono",
396
396
  "clap",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "gitronics"
3
- version = "0.5.7"
3
+ version = "0.5.9"
4
4
  edition = "2024"
5
5
  description = "Build MCNP neutronics models from modular components"
6
6
  license = "EUPL-1.2"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitronics
3
- Version: 0.5.7
3
+ Version: 0.5.9
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Programming Language :: Python :: Implementation :: PyPy
@@ -42,6 +42,26 @@ C ============================================================
42
42
 
43
43
  Gitronics searches all directories listed in `project_roots` (defined in the configuration) for files referenced by stem name. Any file whose stem (name without extension) matches a key in the configuration is a candidate. This means you can organise your project files into subdirectories however you like, as long as each stem name is unique across all `project_roots`.
44
44
 
45
+ ## Python API
46
+
47
+ `build_model` is also available as a Python function for use in scripts and notebooks:
48
+
49
+ ```python
50
+ import gitronics
51
+
52
+ gitronics.build_model(
53
+ "configurations/in_vessel_only.yaml",
54
+ "output/",
55
+ )
56
+ ```
57
+
58
+ | Parameter | Type | Description |
59
+ |---|---|---|
60
+ | `config_path` | `str` or `Path` | Path to the configuration YAML file. |
61
+ | `output_path` | `str` or `Path` | Directory to write `assembled.mcnp` into. |
62
+
63
+ Raises `RuntimeError` on failure with a descriptive message.
64
+
45
65
  ## Logging
46
66
 
47
67
  Set the `RUST_LOG` environment variable to control verbosity:
@@ -10,9 +10,10 @@ from __future__ import annotations
10
10
 
11
11
  import sys
12
12
 
13
+ from .gitronics import py_build_model as build_model # type: ignore[import]
13
14
  from .gitronics import run # type: ignore[import]
14
15
 
15
- __all__ = ["run"]
16
+ __all__ = ["build_model", "run"]
16
17
 
17
18
 
18
19
  def _cli_main() -> None:
@@ -0,0 +1,3 @@
1
+ from gitronics import _cli_main
2
+
3
+ _cli_main()
@@ -0,0 +1,45 @@
1
+ """Type stubs for the gitronics Rust extension module."""
2
+
3
+ from pathlib import Path
4
+
5
+ def run(args: list[str]) -> None:
6
+ """Run the gitronics CLI with the given argument list.
7
+
8
+ This is equivalent to running ``gitronics`` from the command line.
9
+ ``args[0]`` should be the program name (i.e. ``sys.argv``).
10
+
11
+ Args:
12
+ args: Argument list in ``sys.argv`` format, e.g.
13
+ ``["gitronics", "build", "config.yaml"]``.
14
+
15
+ Raises:
16
+ RuntimeError: If the command fails.
17
+ """
18
+ ...
19
+
20
+ def py_build_model(config_path: Path | str, output_path: Path | str) -> None:
21
+ """Assemble an MCNP model from a gitronics configuration file.
22
+
23
+ Reads the YAML configuration at *config_path*, resolves all referenced
24
+ filler models and data-card files, and writes ``assembled.mcnp`` (plus a
25
+ ``.gitignore``) into *output_path*.
26
+
27
+ Args:
28
+ config_path: Path to the YAML configuration file.
29
+ output_path: Directory where ``assembled.mcnp`` will be written.
30
+ The directory must already exist.
31
+
32
+ Raises:
33
+ RuntimeError: If any step of the build fails (e.g. missing file,
34
+ invalid MCNP syntax, validation error).
35
+
36
+ Example::
37
+
38
+ import gitronics
39
+
40
+ gitronics.build_model(
41
+ "configurations/baseline.yaml",
42
+ "output/",
43
+ )
44
+ """
45
+ ...
@@ -0,0 +1,30 @@
1
+ import tempfile
2
+ from pathlib import Path
3
+
4
+ import gitronics
5
+ import pytest
6
+
7
+ EXAMPLE_CONFIG = (
8
+ Path(__file__).parent.parent.parent
9
+ / "example_project"
10
+ / "configurations"
11
+ / "valid_configuration.yaml"
12
+ )
13
+
14
+
15
+ def test_build_model_success():
16
+ with tempfile.TemporaryDirectory() as output_dir:
17
+ gitronics.build_model(EXAMPLE_CONFIG, output_dir)
18
+ assert (Path(output_dir) / "assembled.mcnp").exists()
19
+
20
+
21
+ def test_build_model_accepts_str_paths():
22
+ with tempfile.TemporaryDirectory() as output_dir:
23
+ gitronics.build_model(str(EXAMPLE_CONFIG), output_dir)
24
+ assert (Path(output_dir) / "assembled.mcnp").exists()
25
+
26
+
27
+ def test_build_model_missing_config_raises():
28
+ with tempfile.TemporaryDirectory() as output_dir:
29
+ with pytest.raises(RuntimeError):
30
+ gitronics.build_model("does_not_exist.yaml", output_dir)
@@ -63,6 +63,7 @@ pub fn build_model(config_path: &Path, output_path: &Path) -> Result<(), Gitroni
63
63
  .map_err(|e| GitronicsError::ValidationError(e.to_string()))?;
64
64
 
65
65
  // Write model
66
+ info!("Writing assembled model to file");
66
67
  let assembled_path = project_manager.output_path().join("assembled.mcnp");
67
68
  write_assembled_header(&mut envelope_structure, config_path)?;
68
69
  envelope_structure.write_to_file(&assembled_path)?;
@@ -39,7 +39,8 @@ impl ModelConfig {
39
39
 
40
40
  /// Parses a model configuration from a YAML file.
41
41
  pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self, GitronicsError> {
42
- let yaml_content = fs::read_to_string(&path)?;
42
+ let yaml_content =
43
+ fs::read_to_string(&path).map_err(|source| GitronicsError::io_path(&path, source))?;
43
44
  let mut config: ModelConfig = serde_saphyr::from_str(&yaml_content).map_err(|e| {
44
45
  GitronicsError::YamlParse(path.as_ref().to_string_lossy().to_string(), e.to_string())
45
46
  })?;
@@ -24,7 +24,8 @@ impl ProjectManager {
24
24
  if !metadata_path.exists() {
25
25
  return Err(GitronicsError::MetadataNotFound(filler_name.into()));
26
26
  }
27
- let yaml_content = fs::read_to_string(&metadata_path)?;
27
+ let yaml_content = fs::read_to_string(&metadata_path)
28
+ .map_err(|source| GitronicsError::io_path(&metadata_path, source))?;
28
29
  let filler_metadata: FillerMetadata =
29
30
  serde_saphyr::from_str(&yaml_content).map_err(|e| {
30
31
  GitronicsError::YamlParse(
@@ -0,0 +1,31 @@
1
+ use std::path::PathBuf;
2
+
3
+ use pyo3::prelude::*;
4
+
5
+ use crate::build_model::build_model;
6
+ use crate::run_cli;
7
+
8
+ #[pyfunction]
9
+ fn run(args: Vec<String>) -> PyResult<()> {
10
+ use pyo3::exceptions::PyRuntimeError;
11
+ // Clap exits the process on --help / bad args; that's acceptable.
12
+ run_cli(args).map_err(|e| PyRuntimeError::new_err(e.to_string()))
13
+ }
14
+
15
+ /// Build an MCNP model from a gitronics configuration file.
16
+ ///
17
+ /// Args:
18
+ /// config_path: Path to the YAML configuration file.
19
+ /// output_path: Directory where the assembled model will be written.
20
+ #[pyfunction]
21
+ fn py_build_model(config_path: PathBuf, output_path: PathBuf) -> PyResult<()> {
22
+ use pyo3::exceptions::PyRuntimeError;
23
+ build_model(&config_path, &output_path).map_err(|e| PyRuntimeError::new_err(e.to_string()))
24
+ }
25
+
26
+ /// Python extension module.
27
+ #[pymodule]
28
+ fn gitronics(m: &Bound<'_, PyModule>) -> PyResult<()> {
29
+ m.add_function(wrap_pyfunction!(run, m)?)?;
30
+ m.add_function(wrap_pyfunction!(py_build_model, m)?)
31
+ }
@@ -19,6 +19,13 @@ const VALID_SUFFIXES: &[&str] = &["yaml", "yml", "mcnp", "mat", "tally", "transf
19
19
 
20
20
  #[derive(Debug, Error)]
21
21
  pub enum GitronicsError {
22
+ #[error("I/O error at `{path}`: {source}")]
23
+ IoPath {
24
+ path: String,
25
+ #[source]
26
+ source: io::Error,
27
+ },
28
+
22
29
  #[error("I/O error occurred: `{0}`")]
23
30
  Io(#[from] io::Error),
24
31
 
@@ -81,6 +88,15 @@ pub enum GitronicsError {
81
88
  ValidationError(String),
82
89
  }
83
90
 
91
+ impl GitronicsError {
92
+ pub fn io_path(path: impl AsRef<Path>, source: io::Error) -> Self {
93
+ Self::IoPath {
94
+ path: path.as_ref().display().to_string(),
95
+ source,
96
+ }
97
+ }
98
+ }
99
+
84
100
  /// Recursively discovers and indexes all project files by their stem names.
85
101
  ///
86
102
  /// Walks through the given directory tree and collects files with valid suffixes
@@ -1,16 +0,0 @@
1
- use pyo3::prelude::*;
2
-
3
- use crate::run_cli;
4
-
5
- #[pyfunction]
6
- fn run(args: Vec<String>) -> PyResult<()> {
7
- use pyo3::exceptions::PyRuntimeError;
8
- // Clap exits the process on --help / bad args; that's acceptable.
9
- run_cli(args).map_err(|e| PyRuntimeError::new_err(e.to_string()))
10
- }
11
-
12
- /// Python extension module.
13
- #[pymodule]
14
- fn gitronics(m: &Bound<'_, PyModule>) -> PyResult<()> {
15
- m.add_function(wrap_pyfunction!(run, m)?)
16
- }
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