algorithm-nexus 0.2.1__py3-none-any.whl

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.
@@ -0,0 +1,4 @@
1
+ # Copyright IBM Corp. 2026
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ """Algorithm Nexus package."""
algorithm_nexus/cli.py ADDED
@@ -0,0 +1,101 @@
1
+ # Copyright IBM Corp. 2026
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ """Command-line interface for Algorithm Nexus package validation."""
5
+
6
+ from __future__ import annotations
7
+
8
+ import sys
9
+
10
+ try:
11
+ import typer
12
+ from rich.console import Console
13
+ except ImportError:
14
+ print(
15
+ "Error: CLI dependencies are not installed.\n"
16
+ "Please install them with: pip install algorithm-nexus[cli]",
17
+ file=sys.stderr,
18
+ )
19
+ sys.exit(1)
20
+
21
+ from algorithm_nexus.commands.get import get_benchmark_requirements
22
+ from algorithm_nexus.commands.list import (
23
+ list_benchmark_experiments,
24
+ list_benchmark_packages,
25
+ list_packages,
26
+ )
27
+ from algorithm_nexus.commands.run import run_benchmarks
28
+ from algorithm_nexus.commands.validate import (
29
+ validate_benchmarks,
30
+ validate_logical_benchmarks,
31
+ validate_package,
32
+ )
33
+
34
+ console = Console()
35
+
36
+ app = typer.Typer(
37
+ help="Algorithm Nexus CLI - Tools for managing and validating Nexus packages.",
38
+ add_completion=False,
39
+ no_args_is_help=True,
40
+ )
41
+
42
+ # Create subcommand group for 'list'
43
+ list_app = typer.Typer(
44
+ help="List various resources in Nexus packages.",
45
+ no_args_is_help=True,
46
+ )
47
+ app.add_typer(list_app, name="list")
48
+
49
+ # Create subcommand group for 'get'
50
+ get_app = typer.Typer(
51
+ help="Get specific information about Nexus packages.",
52
+ no_args_is_help=True,
53
+ )
54
+ app.add_typer(get_app, name="get")
55
+
56
+ # Create subcommand group for 'run'
57
+ run_app = typer.Typer(
58
+ help="Execute benchmarks and operations.",
59
+ no_args_is_help=True,
60
+ )
61
+ app.add_typer(run_app, name="run")
62
+
63
+ # Create subcommand group for 'validate'
64
+ validate_app = typer.Typer(
65
+ help="Validate various aspects of Nexus packages.",
66
+ no_args_is_help=True,
67
+ )
68
+ app.add_typer(validate_app, name="validate")
69
+
70
+
71
+ @app.callback(invoke_without_command=True)
72
+ def main_callback(ctx: typer.Context) -> None:
73
+ pass
74
+
75
+
76
+ # Register list commands
77
+ list_app.command(name="packages")(list_packages)
78
+ list_app.command(name="benchmark-packages")(list_benchmark_packages)
79
+ list_app.command(name="benchmark-experiments")(list_benchmark_experiments)
80
+
81
+ # Register get commands
82
+ get_app.command(name="benchmark-requirements")(get_benchmark_requirements)
83
+
84
+ # Register run commands
85
+ run_app.command(name="benchmarks")(run_benchmarks)
86
+
87
+ # Register validate commands
88
+ validate_app.command(name="package")(validate_package)
89
+ validate_app.command(name="benchmarks")(validate_benchmarks)
90
+ validate_app.command(name="logical-benchmarks")(validate_logical_benchmarks)
91
+
92
+
93
+ def main() -> None:
94
+ """Entry point for the CLI application."""
95
+ app()
96
+
97
+
98
+ if __name__ == "__main__":
99
+ main()
100
+
101
+ # Made with Bob
@@ -0,0 +1,6 @@
1
+ # Copyright IBM Corp. 2026
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ """Command implementations for Algorithm Nexus CLI."""
5
+
6
+ # Made with Bob
@@ -0,0 +1,176 @@
1
+ # Copyright IBM Corp. 2026
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ """ADO validation for benchmark instances."""
5
+
6
+ from __future__ import annotations
7
+
8
+ import subprocess
9
+ import sys
10
+ from pathlib import Path
11
+
12
+ import yaml
13
+
14
+ try:
15
+ from ado.core.discoveryspace.config import DiscoverySpaceConfiguration
16
+ from pydantic import ValidationError
17
+ from rich.console import Console
18
+ except ImportError:
19
+ print(
20
+ "Error: CLI dependencies are not installed.\n"
21
+ "Please install them with: pip install algorithm-nexus[cli]",
22
+ file=sys.stderr,
23
+ )
24
+ sys.exit(1)
25
+
26
+ from algorithm_nexus.models import ValidationResult
27
+
28
+ console = Console()
29
+
30
+
31
+ def validate_space_yaml_syntax(base_path: Path, instance_path: str) -> ValidationResult:
32
+ """Validate space.yaml YAML syntax and basic structure using DiscoverySpaceConfiguration.
33
+
34
+ Args:
35
+ base_path: Base path (e.g., repo root or temp directory)
36
+ instance_path: Relative path to the benchmark instance from base_path
37
+
38
+ Returns:
39
+ ValidationResult with syntax validation results
40
+ """
41
+
42
+ # Construct full path to space.yaml
43
+ space_yaml_path = base_path / instance_path / "space.yaml"
44
+
45
+ # Check if file exists
46
+ if not space_yaml_path.is_file():
47
+ return ValidationResult(
48
+ success=False,
49
+ instance_path=instance_path,
50
+ errors=[f"File not found: {space_yaml_path}"],
51
+ warnings=[],
52
+ )
53
+
54
+ errors = []
55
+ warnings = []
56
+
57
+ space_config = None
58
+ try:
59
+ # Load and parse YAML
60
+ space_config_dict = yaml.safe_load(space_yaml_path.read_text())
61
+
62
+ # Validate using DiscoverySpaceConfiguration
63
+ space_config = DiscoverySpaceConfiguration.model_validate(space_config_dict)
64
+
65
+ except yaml.YAMLError as e:
66
+ errors.append(f"Invalid YAML syntax: {e}")
67
+ except ValidationError as e:
68
+ # Extract validation errors from Pydantic
69
+ for error in e.errors():
70
+ loc = " -> ".join(str(x) for x in error["loc"])
71
+ msg = error["msg"]
72
+ errors.append(f"Validation error at {loc}: {msg}")
73
+ except Exception as e:
74
+ errors.append(f"Unexpected error reading space.yaml: {e}")
75
+
76
+ # Check for optional but common sections using the validated model
77
+ if space_config:
78
+ space_config = space_config.convert_experiments_to_reference_list()
79
+ if not space_config.experiments:
80
+ warnings.append("No 'experiments' section found in space.yaml")
81
+
82
+ if not space_config.entitySpace:
83
+ warnings.append("No 'entitySpace' section found in space.yaml")
84
+
85
+ return ValidationResult(
86
+ success=len(errors) == 0,
87
+ instance_path=instance_path,
88
+ errors=errors,
89
+ warnings=warnings,
90
+ )
91
+
92
+
93
+ def validate_with_ado(
94
+ base_path: Path,
95
+ instance_path: str,
96
+ venv_path: Path,
97
+ ) -> ValidationResult:
98
+ """Run ADO validation in isolated virtual environment.
99
+
100
+ Args:
101
+ base_path: Base path (e.g., repo root or temp directory)
102
+ instance_path: Relative path to the benchmark instance from base_path
103
+ venv_path: Path to virtual environment with ADO installed
104
+
105
+ Returns:
106
+ ValidationResult with ADO validation results
107
+ """
108
+ # First validate syntax
109
+ syntax_result = validate_space_yaml_syntax(base_path, instance_path)
110
+
111
+ if syntax_result.errors:
112
+ # Don't proceed with ADO validation if syntax is invalid
113
+ return syntax_result
114
+
115
+ # Start with syntax warnings for ADO validation
116
+ errors = []
117
+ warnings = syntax_result.warnings.copy()
118
+
119
+ # Check if ADO binary is available in the venv
120
+ ado_binary = venv_path / "bin" / "ado"
121
+ if not ado_binary.is_file():
122
+ errors.append(
123
+ "ADO binary not found in the virtual environment. "
124
+ "Make sure ado-core is installed."
125
+ )
126
+ return ValidationResult(
127
+ success=False,
128
+ instance_path=instance_path,
129
+ errors=errors,
130
+ warnings=warnings,
131
+ )
132
+
133
+ # Validate with ADO using dry-run mode
134
+ try:
135
+ # Construct full path to space.yaml
136
+ space_yaml_path = base_path / instance_path / "space.yaml"
137
+
138
+ # Use ado create space with --dry-run flag
139
+ # Run from the benchmark instance directory to support relative paths in space.yaml
140
+ result = subprocess.run( # noqa: S603
141
+ [
142
+ str(ado_binary),
143
+ "create",
144
+ "space",
145
+ "-f",
146
+ str(space_yaml_path),
147
+ "--dry-run",
148
+ ],
149
+ capture_output=True,
150
+ text=True,
151
+ check=False,
152
+ timeout=30, # 30 second timeout
153
+ cwd=space_yaml_path.parent, # Run from benchmark instance directory
154
+ )
155
+
156
+ if result.returncode != 0:
157
+ # Parse error message for more details
158
+ error_msg = (
159
+ result.stderr.strip() if result.stderr else result.stdout.strip()
160
+ )
161
+ errors.append(f"ADO validation failed: {error_msg}")
162
+
163
+ except subprocess.TimeoutExpired:
164
+ errors.append("ADO validation timed out after 30 seconds")
165
+ except Exception as e:
166
+ errors.append(f"Failed to run ADO validation: {e}")
167
+
168
+ return ValidationResult(
169
+ success=len(errors) == 0,
170
+ instance_path=instance_path,
171
+ errors=errors,
172
+ warnings=warnings,
173
+ )
174
+
175
+
176
+ # Made with Bob