rhylthyme-cli-runner 0.1.0a0__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.
- rhylthyme_cli_runner/__init__.py +15 -0
- rhylthyme_cli_runner/cli.py +273 -0
- rhylthyme_cli_runner/environment_icons.py +258 -0
- rhylthyme_cli_runner/environment_loader.py +293 -0
- rhylthyme_cli_runner/environment_schemas.py +443 -0
- rhylthyme_cli_runner/program_planner.py +871 -0
- rhylthyme_cli_runner/program_runner.py +2257 -0
- rhylthyme_cli_runner/validate_program.py +457 -0
- rhylthyme_cli_runner-0.1.0a0.dist-info/METADATA +268 -0
- rhylthyme_cli_runner-0.1.0a0.dist-info/RECORD +13 -0
- rhylthyme_cli_runner-0.1.0a0.dist-info/WHEEL +5 -0
- rhylthyme_cli_runner-0.1.0a0.dist-info/entry_points.txt +2 -0
- rhylthyme_cli_runner-0.1.0a0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Rhylthyme CLI Runner Package
|
|
4
|
+
|
|
5
|
+
This package provides the command-line interface for running and validating
|
|
6
|
+
Rhylthyme real-time program schedules.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
__version__ = "0.1.0-alpha"
|
|
10
|
+
__author__ = "Rhylthyme Team"
|
|
11
|
+
__description__ = "CLI runner for Rhylthyme real-time program schedules"
|
|
12
|
+
|
|
13
|
+
from .cli import cli, main
|
|
14
|
+
|
|
15
|
+
__all__ = ['cli', 'main']
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Command-line interface for Rhylthyme
|
|
4
|
+
|
|
5
|
+
This module provides the command-line interface for the Rhylthyme package,
|
|
6
|
+
allowing users to validate and run real-time program schedules.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
import sys
|
|
11
|
+
import click
|
|
12
|
+
import subprocess
|
|
13
|
+
import pkg_resources
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from .validate_program import validate_program_file
|
|
16
|
+
from .program_runner import run_program
|
|
17
|
+
from .program_planner import plan_program
|
|
18
|
+
from .environment_loader import EnvironmentLoader
|
|
19
|
+
|
|
20
|
+
# Global environment loader instance
|
|
21
|
+
_environment_loader = None
|
|
22
|
+
|
|
23
|
+
def get_environment_loader(environments_dir=None):
|
|
24
|
+
"""Get the environment loader instance, creating it if necessary."""
|
|
25
|
+
global _environment_loader
|
|
26
|
+
|
|
27
|
+
if _environment_loader is None:
|
|
28
|
+
if environments_dir is None:
|
|
29
|
+
# Check for environment variable first
|
|
30
|
+
env_dir = os.environ.get('RHYLTHYME_ENVIRONMENTS_DIR')
|
|
31
|
+
if env_dir:
|
|
32
|
+
environments_dir = env_dir
|
|
33
|
+
else:
|
|
34
|
+
# Check for environments directory in current working directory
|
|
35
|
+
cwd_environments = Path.cwd() / "environments"
|
|
36
|
+
if cwd_environments.exists():
|
|
37
|
+
environments_dir = str(cwd_environments)
|
|
38
|
+
|
|
39
|
+
_environment_loader = EnvironmentLoader(environments_dir)
|
|
40
|
+
|
|
41
|
+
return _environment_loader
|
|
42
|
+
|
|
43
|
+
# Set up the main CLI group
|
|
44
|
+
@click.group()
|
|
45
|
+
@click.option('--environments-dir', type=click.Path(exists=True),
|
|
46
|
+
help='Directory containing environment files (default: check current directory, then package default)')
|
|
47
|
+
@click.version_option()
|
|
48
|
+
@click.pass_context
|
|
49
|
+
def cli(ctx, environments_dir):
|
|
50
|
+
"""
|
|
51
|
+
Rhylthyme - A tool for working with real-time program schedules.
|
|
52
|
+
|
|
53
|
+
This CLI tool provides commands for validating and running real-time
|
|
54
|
+
program schedules defined using the Rhylthyme JSON or YAML schema.
|
|
55
|
+
"""
|
|
56
|
+
# Store the environments directory in the context
|
|
57
|
+
ctx.ensure_object(dict)
|
|
58
|
+
ctx.obj['environments_dir'] = environments_dir
|
|
59
|
+
|
|
60
|
+
# Initialize the environment loader
|
|
61
|
+
get_environment_loader(environments_dir)
|
|
62
|
+
|
|
63
|
+
# Validate command
|
|
64
|
+
@cli.command()
|
|
65
|
+
@click.argument('program_file', type=click.Path(exists=True))
|
|
66
|
+
@click.option('--schema', type=click.Path(exists=True),
|
|
67
|
+
default=lambda: pkg_resources.resource_filename('rhylthyme_spec', 'schemas/program_schema_0.1.0-alpha.json'),
|
|
68
|
+
help='Path to the schema file (default: built-in schema)')
|
|
69
|
+
@click.option('--verbose', '-v', is_flag=True, help='Show detailed validation information')
|
|
70
|
+
@click.option('--json', '-j', 'json_output', is_flag=True, help='Print machine-readable JSON result')
|
|
71
|
+
@click.option('--strict', '-s', is_flag=True, help='Enforce all tasks must be defined in resourceConstraints (strict mode)')
|
|
72
|
+
def validate(program_file, schema, verbose, json_output, strict):
|
|
73
|
+
"""
|
|
74
|
+
Validate a program file against the schema.
|
|
75
|
+
|
|
76
|
+
This command checks if the provided program file (JSON or YAML) conforms to the
|
|
77
|
+
Rhylthyme schema and performs additional semantic validations.
|
|
78
|
+
|
|
79
|
+
Use --json to get machine-readable output for CI or scripting.
|
|
80
|
+
Use --strict to require all tasks used in steps/buffers to be defined in resourceConstraints.
|
|
81
|
+
"""
|
|
82
|
+
success = validate_program_file(program_file, schema, verbose, json_output, strict)
|
|
83
|
+
if not success:
|
|
84
|
+
sys.exit(1)
|
|
85
|
+
|
|
86
|
+
# Run command
|
|
87
|
+
@cli.command()
|
|
88
|
+
@click.argument('program_file', type=click.Path(exists=True))
|
|
89
|
+
@click.option('--schema', type=click.Path(exists=True),
|
|
90
|
+
default=lambda: pkg_resources.resource_filename('rhylthyme_spec', 'schemas/program_schema_0.1.0-alpha.json'),
|
|
91
|
+
help='Path to the schema file (default: built-in schema)')
|
|
92
|
+
@click.option('-e', '--environment', type=str,
|
|
93
|
+
help='Environment file path or ID to use (overrides program environment setting)')
|
|
94
|
+
@click.option('--time-scale', type=float, default=1.0,
|
|
95
|
+
help='Time scale factor (default: 1.0)')
|
|
96
|
+
@click.option('--validate/--no-validate', default=True,
|
|
97
|
+
help='Validate the program before running (default: True)')
|
|
98
|
+
@click.option('--auto-start', is_flag=True,
|
|
99
|
+
help='Automatically start the program without waiting for manual trigger')
|
|
100
|
+
def run(program_file, schema, environment, time_scale, validate, auto_start):
|
|
101
|
+
"""
|
|
102
|
+
Run a program file with the interactive UI.
|
|
103
|
+
|
|
104
|
+
This command executes the provided program file (JSON or YAML) according to the
|
|
105
|
+
Rhylthyme schema and displays an interactive terminal UI for
|
|
106
|
+
monitoring and controlling the execution.
|
|
107
|
+
|
|
108
|
+
Use -e/--environment to specify which environment to use when running the program.
|
|
109
|
+
This overrides any environment specified in the program file.
|
|
110
|
+
"""
|
|
111
|
+
run_program(program_file, schema, time_scale, validate, auto_start, environment)
|
|
112
|
+
|
|
113
|
+
# Plan command
|
|
114
|
+
@cli.command()
|
|
115
|
+
@click.argument('input_file', type=click.Path(exists=True))
|
|
116
|
+
@click.argument('output_file', type=click.Path())
|
|
117
|
+
@click.option('-e', '--environment', type=str, help='Environment file path to use for planning')
|
|
118
|
+
@click.option('--verbose', '-v', is_flag=True, help='Show detailed planning information')
|
|
119
|
+
def plan(input_file, output_file, environment, verbose):
|
|
120
|
+
"""
|
|
121
|
+
Optimize a program schedule to reduce resource contention.
|
|
122
|
+
|
|
123
|
+
This command analyzes the provided program file (JSON or YAML) for resource
|
|
124
|
+
bottlenecks and creates an optimized version by staggering track and step
|
|
125
|
+
starts to reduce contention at critical junctures.
|
|
126
|
+
|
|
127
|
+
The optimized program is saved to the specified output file.
|
|
128
|
+
"""
|
|
129
|
+
success = plan_program(input_file, output_file, verbose, environment_file=environment)
|
|
130
|
+
if not success:
|
|
131
|
+
sys.exit(1)
|
|
132
|
+
|
|
133
|
+
click.echo(f"Optimized program saved to {output_file}")
|
|
134
|
+
click.echo("Run the optimized program with:")
|
|
135
|
+
click.echo(f" rhylthyme run {output_file}")
|
|
136
|
+
|
|
137
|
+
# Environments command
|
|
138
|
+
@cli.command()
|
|
139
|
+
@click.option('--format', '-f', type=click.Choice(['table', 'json', 'yaml']), default='table',
|
|
140
|
+
help='Output format (default: table)')
|
|
141
|
+
def environments(format):
|
|
142
|
+
"""
|
|
143
|
+
List all available environment catalogs.
|
|
144
|
+
|
|
145
|
+
This command displays all environment catalogs that can be referenced
|
|
146
|
+
by programs. Each environment defines resource constraints for different
|
|
147
|
+
settings like restaurants, bakeries, laboratories, etc.
|
|
148
|
+
"""
|
|
149
|
+
loader = get_environment_loader()
|
|
150
|
+
envs = loader.list_environments()
|
|
151
|
+
|
|
152
|
+
if not envs:
|
|
153
|
+
click.echo("No environment catalogs found.")
|
|
154
|
+
return
|
|
155
|
+
|
|
156
|
+
if format == 'json':
|
|
157
|
+
import json
|
|
158
|
+
click.echo(json.dumps(envs, indent=2))
|
|
159
|
+
elif format == 'yaml':
|
|
160
|
+
import yaml
|
|
161
|
+
click.echo(yaml.dump(envs, default_flow_style=False))
|
|
162
|
+
else: # table format
|
|
163
|
+
# Calculate column widths
|
|
164
|
+
id_width = max(len(env['id']) for env in envs) + 2
|
|
165
|
+
name_width = max(len(env['name']) for env in envs) + 2
|
|
166
|
+
type_width = max(len(env['type']) for env in envs) + 2
|
|
167
|
+
icon_width = max(len(env.get('icon', '')) for env in envs) + 2
|
|
168
|
+
|
|
169
|
+
# Print header
|
|
170
|
+
click.echo(f"{'ID':<{id_width}}{'Name':<{name_width}}{'Type':<{type_width}}{'Icon':<{icon_width}}Description")
|
|
171
|
+
click.echo(f"{'-' * id_width}{'-' * name_width}{'-' * type_width}{'-' * icon_width}{'-' * 40}")
|
|
172
|
+
|
|
173
|
+
# Print environments
|
|
174
|
+
for env in envs:
|
|
175
|
+
description = env['description']
|
|
176
|
+
if len(description) > 40:
|
|
177
|
+
description = description[:37] + "..."
|
|
178
|
+
icon = env.get('icon', 'fa-building')
|
|
179
|
+
click.echo(f"{env['id']:<{id_width}}{env['name']:<{name_width}}{env['type']:<{type_width}}{icon:<{icon_width}}{description}")
|
|
180
|
+
|
|
181
|
+
# Validate environments command
|
|
182
|
+
@cli.command('validate-environments')
|
|
183
|
+
@click.option('--environments-dir', type=click.Path(exists=True), default='environments',
|
|
184
|
+
help='Directory containing environment files (default: environments)')
|
|
185
|
+
@click.option('--verbose', '-v', is_flag=True, help='Show detailed validation information')
|
|
186
|
+
def validate_environments(environments_dir, verbose):
|
|
187
|
+
"""
|
|
188
|
+
Validate all environment catalog files against their schemas.
|
|
189
|
+
|
|
190
|
+
This command checks if environment files conform to the base environment
|
|
191
|
+
schema and validates type-specific requirements (e.g., kitchen environments
|
|
192
|
+
should have appropriate kitchen tasks and equipment).
|
|
193
|
+
"""
|
|
194
|
+
try:
|
|
195
|
+
from .environment_schemas import validate_all_environments, EnvironmentValidator
|
|
196
|
+
except ImportError:
|
|
197
|
+
click.echo("Error: Environment validation not available. Missing dependencies.")
|
|
198
|
+
sys.exit(1)
|
|
199
|
+
|
|
200
|
+
click.echo(f"Validating environments in: {environments_dir}")
|
|
201
|
+
validation_results = validate_all_environments(environments_dir)
|
|
202
|
+
|
|
203
|
+
if not validation_results:
|
|
204
|
+
click.echo("✓ All environment files are valid!")
|
|
205
|
+
return
|
|
206
|
+
|
|
207
|
+
# Count errors vs warnings
|
|
208
|
+
total_errors = 0
|
|
209
|
+
total_warnings = 0
|
|
210
|
+
|
|
211
|
+
for filename, errors in validation_results.items():
|
|
212
|
+
click.echo(f"\n{filename}:")
|
|
213
|
+
for error in errors:
|
|
214
|
+
if error.startswith("Warning:"):
|
|
215
|
+
total_warnings += 1
|
|
216
|
+
if verbose:
|
|
217
|
+
click.echo(f" ⚠️ {error}")
|
|
218
|
+
else:
|
|
219
|
+
total_errors += 1
|
|
220
|
+
click.echo(f" ❌ {error}")
|
|
221
|
+
|
|
222
|
+
if total_errors > 0:
|
|
223
|
+
click.echo(f"\n❌ Validation failed: {total_errors} errors found")
|
|
224
|
+
if total_warnings > 0:
|
|
225
|
+
click.echo(f"⚠️ {total_warnings} warnings found")
|
|
226
|
+
sys.exit(1)
|
|
227
|
+
elif total_warnings > 0:
|
|
228
|
+
click.echo(f"\n⚠️ Validation passed with {total_warnings} warnings")
|
|
229
|
+
if not verbose:
|
|
230
|
+
click.echo("Use --verbose to see warning details")
|
|
231
|
+
else:
|
|
232
|
+
click.echo("✓ All environment files are valid!")
|
|
233
|
+
|
|
234
|
+
# Environment info command
|
|
235
|
+
@cli.command('environment-info')
|
|
236
|
+
@click.argument('environment_type')
|
|
237
|
+
def environment_info(environment_type):
|
|
238
|
+
"""
|
|
239
|
+
Show information about a specific environment type.
|
|
240
|
+
|
|
241
|
+
This command displays the required tasks, common tasks, and suggested
|
|
242
|
+
actor types for a given environment type (e.g., kitchen, laboratory, bakery).
|
|
243
|
+
"""
|
|
244
|
+
try:
|
|
245
|
+
from .environment_schemas import EnvironmentValidator
|
|
246
|
+
from .environment_icons import get_environment_icon
|
|
247
|
+
except ImportError:
|
|
248
|
+
click.echo("Error: Environment schemas not available.")
|
|
249
|
+
sys.exit(1)
|
|
250
|
+
|
|
251
|
+
validator = EnvironmentValidator()
|
|
252
|
+
info = validator.get_environment_type_info(environment_type)
|
|
253
|
+
|
|
254
|
+
if not info:
|
|
255
|
+
click.echo(f"Unknown environment type: {environment_type}")
|
|
256
|
+
click.echo(f"Supported types: {', '.join(sorted(validator.list_supported_types()))}")
|
|
257
|
+
sys.exit(1)
|
|
258
|
+
|
|
259
|
+
# Get icon
|
|
260
|
+
icon = get_environment_icon(environment_type)
|
|
261
|
+
|
|
262
|
+
click.echo(f"Environment Type: {environment_type}")
|
|
263
|
+
click.echo(f"Icon: {icon}")
|
|
264
|
+
click.echo(f"Required Tasks: {', '.join(info.get('required_tasks', []))}")
|
|
265
|
+
click.echo(f"Common Tasks: {', '.join(info.get('common_tasks', []))}")
|
|
266
|
+
click.echo(f"Actor Types: {', '.join(info.get('actor_types', []))}")
|
|
267
|
+
|
|
268
|
+
def main():
|
|
269
|
+
"""Entry point for the CLI."""
|
|
270
|
+
cli()
|
|
271
|
+
|
|
272
|
+
if __name__ == '__main__':
|
|
273
|
+
main()
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Environment Icons Index
|
|
4
|
+
|
|
5
|
+
This module provides a mapping of environment types to appropriate FontAwesome icons
|
|
6
|
+
for use in visualizations and user interfaces.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import Dict, List, Optional
|
|
10
|
+
|
|
11
|
+
# Environment Types to FontAwesome Icons Mapping
|
|
12
|
+
ENVIRONMENT_ICONS: Dict[str, str] = {
|
|
13
|
+
# Kitchen environments
|
|
14
|
+
"kitchen": "fa-utensils",
|
|
15
|
+
"home": "fa-house",
|
|
16
|
+
"restaurant": "fa-utensils",
|
|
17
|
+
"commercial-kitchen": "fa-fire-burner",
|
|
18
|
+
|
|
19
|
+
# Laboratory environments
|
|
20
|
+
"laboratory": "fa-flask",
|
|
21
|
+
"lab": "fa-flask",
|
|
22
|
+
"research": "fa-microscope",
|
|
23
|
+
"biotech": "fa-dna",
|
|
24
|
+
"pharma": "fa-pills",
|
|
25
|
+
"medical": "fa-user-doctor",
|
|
26
|
+
|
|
27
|
+
# Bakery environments
|
|
28
|
+
"bakery": "fa-bread-slice",
|
|
29
|
+
"artisan": "fa-wheat-awn",
|
|
30
|
+
"pastry": "fa-cake-candles",
|
|
31
|
+
|
|
32
|
+
# Airport environments
|
|
33
|
+
"airport": "fa-plane",
|
|
34
|
+
"aviation": "fa-plane-departure",
|
|
35
|
+
"runway": "fa-plane-arrival",
|
|
36
|
+
"terminal": "fa-building",
|
|
37
|
+
|
|
38
|
+
# Additional environment types
|
|
39
|
+
"manufacturing": "fa-industry",
|
|
40
|
+
"warehouse": "fa-warehouse",
|
|
41
|
+
"office": "fa-building",
|
|
42
|
+
"hospital": "fa-hospital",
|
|
43
|
+
"school": "fa-graduation-cap",
|
|
44
|
+
"retail": "fa-store",
|
|
45
|
+
"farm": "fa-tractor",
|
|
46
|
+
"datacenter": "fa-server",
|
|
47
|
+
"factory": "fa-gear",
|
|
48
|
+
"workshop": "fa-screwdriver-wrench",
|
|
49
|
+
"garage": "fa-car",
|
|
50
|
+
"gym": "fa-dumbbell",
|
|
51
|
+
"studio": "fa-microphone",
|
|
52
|
+
"theater": "fa-masks-theater",
|
|
53
|
+
"library": "fa-book",
|
|
54
|
+
"garden": "fa-seedling",
|
|
55
|
+
"greenhouse": "fa-leaf",
|
|
56
|
+
"clinic": "fa-stethoscope",
|
|
57
|
+
"spa": "fa-spa",
|
|
58
|
+
"hotel": "fa-bed",
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
# Default icon for unknown environment types
|
|
62
|
+
DEFAULT_ENVIRONMENT_ICON = "fa-building"
|
|
63
|
+
|
|
64
|
+
# Icon categories for organization
|
|
65
|
+
ICON_CATEGORIES: Dict[str, List[str]] = {
|
|
66
|
+
"food_service": [
|
|
67
|
+
"kitchen", "restaurant", "commercial-kitchen", "bakery",
|
|
68
|
+
"artisan", "pastry", "home"
|
|
69
|
+
],
|
|
70
|
+
"research_science": [
|
|
71
|
+
"laboratory", "lab", "research", "biotech", "pharma", "medical"
|
|
72
|
+
],
|
|
73
|
+
"transportation": [
|
|
74
|
+
"airport", "aviation", "runway", "terminal"
|
|
75
|
+
],
|
|
76
|
+
"industrial": [
|
|
77
|
+
"manufacturing", "warehouse", "factory", "workshop", "garage"
|
|
78
|
+
],
|
|
79
|
+
"commercial": [
|
|
80
|
+
"office", "retail", "store", "hotel"
|
|
81
|
+
],
|
|
82
|
+
"healthcare": [
|
|
83
|
+
"hospital", "clinic", "spa"
|
|
84
|
+
],
|
|
85
|
+
"educational": [
|
|
86
|
+
"school", "library"
|
|
87
|
+
],
|
|
88
|
+
"entertainment": [
|
|
89
|
+
"gym", "studio", "theater"
|
|
90
|
+
],
|
|
91
|
+
"agricultural": [
|
|
92
|
+
"farm", "garden", "greenhouse"
|
|
93
|
+
],
|
|
94
|
+
"technology": [
|
|
95
|
+
"datacenter"
|
|
96
|
+
]
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def get_environment_icon(environment_type: str) -> str:
|
|
101
|
+
"""
|
|
102
|
+
Get the FontAwesome icon class for a given environment type.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
environment_type: The type of environment (e.g., 'kitchen', 'laboratory')
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
FontAwesome icon class string (e.g., 'fa-utensils')
|
|
109
|
+
"""
|
|
110
|
+
if not environment_type:
|
|
111
|
+
return DEFAULT_ENVIRONMENT_ICON
|
|
112
|
+
|
|
113
|
+
# Normalize the environment type (lowercase, handle common variations)
|
|
114
|
+
normalized_type = environment_type.lower().strip()
|
|
115
|
+
|
|
116
|
+
# Direct lookup
|
|
117
|
+
if normalized_type in ENVIRONMENT_ICONS:
|
|
118
|
+
return ENVIRONMENT_ICONS[normalized_type]
|
|
119
|
+
|
|
120
|
+
# Try partial matches for compound names
|
|
121
|
+
for env_type, icon in ENVIRONMENT_ICONS.items():
|
|
122
|
+
if env_type in normalized_type or normalized_type in env_type:
|
|
123
|
+
return icon
|
|
124
|
+
|
|
125
|
+
# Return default if no match found
|
|
126
|
+
return DEFAULT_ENVIRONMENT_ICON
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def get_environment_icon_with_prefix(environment_type: str, prefix: str = "fas") -> str:
|
|
130
|
+
"""
|
|
131
|
+
Get the complete FontAwesome icon class with prefix for a given environment type.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
environment_type: The type of environment
|
|
135
|
+
prefix: FontAwesome prefix (e.g., 'fas', 'far', 'fab')
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
Complete FontAwesome icon class string (e.g., 'fas fa-utensils')
|
|
139
|
+
"""
|
|
140
|
+
icon = get_environment_icon(environment_type)
|
|
141
|
+
return f"{prefix} {icon}"
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def get_icon_category(environment_type: str) -> Optional[str]:
|
|
145
|
+
"""
|
|
146
|
+
Get the category that an environment type belongs to.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
environment_type: The type of environment
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
Category name or None if not found
|
|
153
|
+
"""
|
|
154
|
+
normalized_type = environment_type.lower().strip() if environment_type else ""
|
|
155
|
+
|
|
156
|
+
for category, types in ICON_CATEGORIES.items():
|
|
157
|
+
if normalized_type in types:
|
|
158
|
+
return category
|
|
159
|
+
|
|
160
|
+
return None
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def list_environment_types() -> List[str]:
|
|
164
|
+
"""
|
|
165
|
+
Get a list of all supported environment types.
|
|
166
|
+
|
|
167
|
+
Returns:
|
|
168
|
+
List of environment type strings
|
|
169
|
+
"""
|
|
170
|
+
return list(ENVIRONMENT_ICONS.keys())
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def list_environment_types_by_category() -> Dict[str, List[str]]:
|
|
174
|
+
"""
|
|
175
|
+
Get all environment types organized by category.
|
|
176
|
+
|
|
177
|
+
Returns:
|
|
178
|
+
Dictionary mapping category names to lists of environment types
|
|
179
|
+
"""
|
|
180
|
+
return ICON_CATEGORIES.copy()
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def search_environment_types(query: str) -> List[str]:
|
|
184
|
+
"""
|
|
185
|
+
Search for environment types that match a query string.
|
|
186
|
+
|
|
187
|
+
Args:
|
|
188
|
+
query: Search query string
|
|
189
|
+
|
|
190
|
+
Returns:
|
|
191
|
+
List of matching environment types
|
|
192
|
+
"""
|
|
193
|
+
query_lower = query.lower().strip()
|
|
194
|
+
matches = []
|
|
195
|
+
|
|
196
|
+
for env_type in ENVIRONMENT_ICONS.keys():
|
|
197
|
+
if query_lower in env_type.lower():
|
|
198
|
+
matches.append(env_type)
|
|
199
|
+
|
|
200
|
+
return sorted(matches)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
# Validation function to ensure all referenced icons exist in FontAwesome
|
|
204
|
+
def validate_icons() -> Dict[str, bool]:
|
|
205
|
+
"""
|
|
206
|
+
Validate that all icons in the mapping are valid FontAwesome icons.
|
|
207
|
+
Note: This is a basic check based on common FontAwesome patterns.
|
|
208
|
+
For complete validation, you would need to check against the FontAwesome icon list.
|
|
209
|
+
|
|
210
|
+
Returns:
|
|
211
|
+
Dictionary mapping icon names to validation status
|
|
212
|
+
"""
|
|
213
|
+
validation_results = {}
|
|
214
|
+
|
|
215
|
+
# Common FontAwesome icon patterns for basic validation
|
|
216
|
+
valid_patterns = [
|
|
217
|
+
"fa-", "fa-solid", "fa-regular", "fa-light", "fa-thin", "fa-duotone", "fa-brands"
|
|
218
|
+
]
|
|
219
|
+
|
|
220
|
+
for env_type, icon in ENVIRONMENT_ICONS.items():
|
|
221
|
+
# Basic validation: check if it starts with fa-
|
|
222
|
+
is_valid = icon.startswith("fa-") and len(icon) > 3
|
|
223
|
+
validation_results[icon] = is_valid
|
|
224
|
+
|
|
225
|
+
return validation_results
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
if __name__ == "__main__":
|
|
229
|
+
# Example usage and testing
|
|
230
|
+
print("Environment Icons Index")
|
|
231
|
+
print("=" * 40)
|
|
232
|
+
|
|
233
|
+
# Test the specific environment types requested
|
|
234
|
+
test_types = ["kitchen", "laboratory", "bakery", "airport"]
|
|
235
|
+
|
|
236
|
+
print("\nRequested Environment Types:")
|
|
237
|
+
for env_type in test_types:
|
|
238
|
+
icon = get_environment_icon(env_type)
|
|
239
|
+
full_icon = get_environment_icon_with_prefix(env_type)
|
|
240
|
+
category = get_icon_category(env_type)
|
|
241
|
+
print(f" {env_type:12} -> {icon:20} ({full_icon}) [Category: {category}]")
|
|
242
|
+
|
|
243
|
+
print(f"\nTotal supported environment types: {len(list_environment_types())}")
|
|
244
|
+
|
|
245
|
+
print("\nEnvironment Types by Category:")
|
|
246
|
+
for category, types in list_environment_types_by_category().items():
|
|
247
|
+
print(f" {category:15}: {', '.join(types)}")
|
|
248
|
+
|
|
249
|
+
print(f"\nDefault icon: {DEFAULT_ENVIRONMENT_ICON}")
|
|
250
|
+
|
|
251
|
+
# Icon validation
|
|
252
|
+
print("\nIcon Validation Results:")
|
|
253
|
+
validation = validate_icons()
|
|
254
|
+
invalid_icons = [icon for icon, valid in validation.items() if not valid]
|
|
255
|
+
if invalid_icons:
|
|
256
|
+
print(f" Invalid icons found: {invalid_icons}")
|
|
257
|
+
else:
|
|
258
|
+
print(" All icons appear to be valid FontAwesome patterns")
|