oasr 0.5.0__py3-none-any.whl → 0.5.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.
cli.py CHANGED
@@ -13,7 +13,7 @@ from pathlib import Path
13
13
  from commands import adapter, clean, clone, config, diff, exec, find, registry, sync, update, use, validate
14
14
  from commands import help as help_cmd
15
15
 
16
- __version__ = "0.5.0"
16
+ __version__ = "0.5.1"
17
17
 
18
18
 
19
19
  def main(argv: list[str] | None = None) -> int:
commands/config.py CHANGED
@@ -3,8 +3,9 @@
3
3
  import argparse
4
4
  import sys
5
5
 
6
- from agents import detect_available_agents, get_all_agent_names
6
+ from agents import detect_available_agents
7
7
  from config import CONFIG_FILE, load_config, save_config
8
+ from config.schema import validate_agent, validate_profile_reference
8
9
 
9
10
 
10
11
  def register(subparsers: argparse._SubParsersAction) -> None:
@@ -25,6 +26,11 @@ def register(subparsers: argparse._SubParsersAction) -> None:
25
26
  )
26
27
  set_parser.add_argument("key", help="Configuration key (e.g., 'agent')")
27
28
  set_parser.add_argument("value", help="Configuration value")
29
+ set_parser.add_argument(
30
+ "--force",
31
+ action="store_true",
32
+ help="Skip validation (use carefully)",
33
+ )
28
34
  set_parser.set_defaults(func=run_set)
29
35
 
30
36
  # config get
@@ -57,40 +63,86 @@ def register(subparsers: argparse._SubParsersAction) -> None:
57
63
 
58
64
 
59
65
  def run_set(args: argparse.Namespace) -> int:
60
- """Set a configuration value."""
66
+ """Set a configuration value with validation."""
61
67
  key = args.key.lower()
62
68
  value = args.value
69
+ force = getattr(args, "force", False)
63
70
 
64
- # Only support agent for now
65
- if key == "agent":
66
- # Validate agent name
67
- valid_agents = get_all_agent_names()
68
- if value not in valid_agents:
69
- print(
70
- f"Error: Invalid agent '{value}'. Must be one of: {', '.join(valid_agents)}",
71
- file=sys.stderr,
72
- )
71
+ # Parse key (support dotted notation like "validation.strict")
72
+ if "." in key:
73
+ parts = key.split(".", 1)
74
+ if len(parts) != 2:
75
+ print(f"Error: Invalid key '{key}'. Use format 'section.field' or 'agent'", file=sys.stderr)
73
76
  return 1
77
+ section, field = parts
78
+ elif key == "agent":
79
+ # Special case: bare "agent" means "agent.default"
80
+ section, field = "agent", "default"
81
+ else:
82
+ print(f"Error: Invalid key '{key}'. Use format 'section.field' or 'agent'", file=sys.stderr)
83
+ return 1
74
84
 
75
- # Load config, update, save
76
- config = load_config(args.config if hasattr(args, "config") else None)
77
- config["agent"]["default"] = value
78
- save_config(config, args.config if hasattr(args, "config") else None)
85
+ # Type coercion based on field
86
+ original_value = value
87
+ if field == "strict":
88
+ value = value.lower() in ("true", "1", "yes", "on")
89
+ elif field == "reference_max_lines":
90
+ try:
91
+ value = int(value)
92
+ if value < 1:
93
+ print(f"Error: '{field}' must be a positive integer", file=sys.stderr)
94
+ return 1
95
+ except ValueError:
96
+ print(f"Error: '{field}' must be an integer", file=sys.stderr)
97
+ return 1
79
98
 
80
- # Show available vs configured
81
- available = detect_available_agents()
82
- if value in available:
83
- print(f"✓ Default agent set to: {value}")
99
+ # Load config
100
+ config_path = getattr(args, "config", None)
101
+ config = load_config(config_path=config_path)
102
+
103
+ # Validate before setting (unless --force)
104
+ if not force:
105
+ # Validate agent
106
+ if section == "agent" and field == "default":
107
+ is_valid, error_msg = validate_agent(value)
108
+ if not is_valid:
109
+ print(f"Error: {error_msg}", file=sys.stderr)
110
+ print("\nTo set anyway, use: oasr config set --force agent <name>", file=sys.stderr)
111
+ return 1
112
+
113
+ # Validate profile reference
114
+ if section == "oasr" and field == "default_profile":
115
+ is_valid, error_msg = validate_profile_reference(value, config)
116
+ if not is_valid:
117
+ print(f"Error: {error_msg}", file=sys.stderr)
118
+ print("\nCreate the profile in ~/.oasr/config.toml first, or use:", file=sys.stderr)
119
+ print(f" oasr config set --force oasr.default_profile {value}", file=sys.stderr)
120
+ return 1
121
+
122
+ # Set the value
123
+ if section not in config:
124
+ config[section] = {}
125
+
126
+ config[section][field] = value
127
+
128
+ try:
129
+ save_config(config, config_path=config_path)
130
+
131
+ # Show confirmation
132
+ if section == "agent" and field == "default":
133
+ # Special handling for agent - check if available
134
+ available = detect_available_agents()
135
+ if value in available:
136
+ print(f"✓ Default agent set to: {value}")
137
+ else:
138
+ print(f"✓ Default agent set to: {value}")
139
+ print(f" Warning: '{value}' binary not found in PATH. Install it to use this agent.", file=sys.stderr)
84
140
  else:
85
- print(f"✓ Default agent set to: {value}")
86
- print(
87
- f" Warning: '{value}' binary not found in PATH. Install it to use this agent.",
88
- file=sys.stderr,
89
- )
141
+ print(f"✓ Set {section}.{field} = {original_value}")
90
142
 
91
143
  return 0
92
- else:
93
- print(f"Error: Unsupported config key '{key}'. Only 'agent' is supported.", file=sys.stderr)
144
+ except ValueError as e:
145
+ print(f"Error: {e}", file=sys.stderr)
94
146
  return 1
95
147
 
96
148
 
commands/exec.py CHANGED
@@ -101,18 +101,30 @@ def run(args: argparse.Namespace) -> int:
101
101
  # Error already printed by _get_user_prompt
102
102
  return 1
103
103
 
104
- # Determine which agent to use
105
- agent_name = _get_agent_name(args)
106
- if agent_name is None:
107
- # Error already printed by _get_agent_name
108
- return 1
109
-
110
104
  # === POLICY ENFORCEMENT ===
111
- # Load configuration
112
- config = load_config()
105
+ # Build CLI overrides for config loading
106
+ cli_overrides = {}
107
+ if args.agent:
108
+ cli_overrides["agent"] = {"default": args.agent}
109
+ if args.profile:
110
+ cli_overrides["oasr"] = cli_overrides.get("oasr", {})
111
+ cli_overrides["oasr"]["default_profile"] = args.profile
112
+
113
+ # Load configuration with precedence: CLI > env > file > defaults
114
+ config = load_config(cli_overrides=cli_overrides)
113
115
 
114
- # Determine which profile to use (flag overrides config)
115
- profile_name = args.profile if args.profile else config.get("oasr", {}).get("default_profile", "safe")
116
+ # Determine agent and profile from merged config
117
+ agent_name = config.get("agent", {}).get("default")
118
+ profile_name = config.get("oasr", {}).get("default_profile", "safe")
119
+
120
+ # Validate agent is set
121
+ if not agent_name:
122
+ print(
123
+ "Error: No agent configured. Set OASR_AGENT, use --agent flag, or run:",
124
+ file=sys.stderr,
125
+ )
126
+ print(" oasr config set agent <name>", file=sys.stderr)
127
+ return 1
116
128
 
117
129
  # Load the policy profile
118
130
  profile = policy.load(config, profile_name)
config/__init__.py CHANGED
@@ -12,6 +12,7 @@ else:
12
12
  import tomli_w
13
13
 
14
14
  from config.defaults import DEFAULT_CONFIG
15
+ from config.env import load_env_config, merge_configs
15
16
  from config.schema import validate_config
16
17
 
17
18
  OASR_DIR = Path.home() / ".oasr"
@@ -40,19 +41,27 @@ def ensure_skills_dir() -> Path:
40
41
  return ensure_oasr_dir()
41
42
 
42
43
 
43
- def load_config(config_path: Path | None = None) -> dict[str, Any]:
44
- """Load configuration from TOML file.
44
+ def load_config(config_path: Path | None = None, cli_overrides: dict[str, Any] | None = None) -> dict[str, Any]:
45
+ """Load configuration from multiple sources with precedence.
46
+
47
+ Precedence order (highest to lowest):
48
+ 1. cli_overrides - explicit CLI flags
49
+ 2. Environment variables (OASR_*)
50
+ 3. Config file (~/.oasr/config.toml)
51
+ 4. Built-in defaults
45
52
 
46
53
  Args:
47
54
  config_path: Override config file path. Defaults to ~/.oasr/config.toml.
55
+ cli_overrides: Optional CLI flag overrides (highest precedence)
48
56
 
49
57
  Returns:
50
- Configuration dictionary with defaults applied.
58
+ Merged configuration dictionary with all sources applied.
51
59
  """
52
60
  path = config_path or CONFIG_FILE
61
+ cli_overrides = cli_overrides or {}
53
62
 
54
63
  # Deep copy defaults
55
- config = {
64
+ defaults = {
56
65
  "validation": DEFAULT_CONFIG["validation"].copy(),
57
66
  "adapter": DEFAULT_CONFIG["adapter"].copy(),
58
67
  "agent": DEFAULT_CONFIG["agent"].copy(),
@@ -60,22 +69,22 @@ def load_config(config_path: Path | None = None) -> dict[str, Any]:
60
69
  "profiles": {k: v.copy() for k, v in DEFAULT_CONFIG["profiles"].items()},
61
70
  }
62
71
 
72
+ # Load config file
73
+ file_config = {}
63
74
  if path.exists():
64
75
  with open(path, "rb") as f:
65
- loaded = tomllib.load(f)
66
-
67
- if "validation" in loaded:
68
- config["validation"].update(loaded["validation"])
69
- if "adapter" in loaded:
70
- config["adapter"].update(loaded["adapter"])
71
- if "agent" in loaded:
72
- config["agent"].update(loaded["agent"])
73
- if "oasr" in loaded:
74
- config["oasr"].update(loaded["oasr"])
75
- if "profiles" in loaded:
76
- # Merge user profiles with defaults (user profiles take precedence)
77
- for profile_name, profile_data in loaded["profiles"].items():
78
- config["profiles"][profile_name] = profile_data
76
+ file_config = tomllib.load(f)
77
+
78
+ # Load environment variables
79
+ env_config = load_env_config()
80
+
81
+ # Merge all sources with precedence
82
+ config = merge_configs(
83
+ cli_overrides=cli_overrides,
84
+ env_config=env_config,
85
+ file_config=file_config,
86
+ defaults=defaults,
87
+ )
79
88
 
80
89
  return config
81
90
 
config/env.py ADDED
@@ -0,0 +1,248 @@
1
+ """Environment variable configuration support.
2
+
3
+ This module provides functionality to load OASR configuration from environment
4
+ variables, following the pattern: OASR_<SECTION>_<KEY>
5
+
6
+ Precedence order:
7
+ 1. CLI flags (highest)
8
+ 2. Environment variables
9
+ 3. Config file
10
+ 4. Built-in defaults (lowest)
11
+
12
+ Environment variable naming:
13
+ - Prefix: OASR_
14
+ - Format: OASR_<SECTION>_<KEY> (uppercase, underscore-separated)
15
+ - Examples:
16
+ OASR_AGENT=codex → agent.default = "codex"
17
+ OASR_PROFILE=dev → oasr.default_profile = "dev"
18
+ OASR_VALIDATION_STRICT=true → validation.strict = true
19
+
20
+ Type handling:
21
+ - Strings: as-is
22
+ - Booleans: true/false, 1/0, yes/no, on/off (case-insensitive)
23
+ - Integers: parsed with int()
24
+ - Lists: comma-separated values
25
+ """
26
+
27
+ import os
28
+ from typing import Any
29
+
30
+ # Mapping of environment variable names to config paths
31
+ ENV_VAR_MAP = {
32
+ "OASR_AGENT": ("agent", "default"),
33
+ "OASR_PROFILE": ("oasr", "default_profile"),
34
+ "OASR_VALIDATION_STRICT": ("validation", "strict"),
35
+ "OASR_VALIDATION_MAX_LINES": ("validation", "reference_max_lines"),
36
+ "OASR_ADAPTER_TARGETS": ("adapter", "default_targets"),
37
+ }
38
+
39
+
40
+ def parse_bool(value: str) -> bool:
41
+ """Parse boolean from string.
42
+
43
+ Args:
44
+ value: String value to parse
45
+
46
+ Returns:
47
+ Boolean value
48
+
49
+ Raises:
50
+ ValueError: If value cannot be parsed as boolean
51
+ """
52
+ value_lower = value.lower()
53
+ if value_lower in ("true", "1", "yes", "on"):
54
+ return True
55
+ if value_lower in ("false", "0", "no", "off"):
56
+ return False
57
+ raise ValueError(f"Cannot parse '{value}' as boolean")
58
+
59
+
60
+ def parse_int(value: str) -> int:
61
+ """Parse integer from string.
62
+
63
+ Args:
64
+ value: String value to parse
65
+
66
+ Returns:
67
+ Integer value
68
+
69
+ Raises:
70
+ ValueError: If value cannot be parsed as integer
71
+ """
72
+ return int(value)
73
+
74
+
75
+ def parse_list(value: str) -> list[str]:
76
+ """Parse list from comma-separated string.
77
+
78
+ Args:
79
+ value: Comma-separated string
80
+
81
+ Returns:
82
+ List of strings (trimmed)
83
+ """
84
+ return [item.strip() for item in value.split(",") if item.strip()]
85
+
86
+
87
+ def parse_value(value: str, expected_type: type) -> Any:
88
+ """Parse environment variable value based on expected type.
89
+
90
+ Args:
91
+ value: String value from environment
92
+ expected_type: Expected Python type
93
+
94
+ Returns:
95
+ Parsed value of appropriate type
96
+
97
+ Raises:
98
+ ValueError: If value cannot be parsed to expected type
99
+ """
100
+ if expected_type is bool:
101
+ return parse_bool(value)
102
+ elif expected_type is int:
103
+ return parse_int(value)
104
+ elif expected_type is list:
105
+ return parse_list(value)
106
+ else:
107
+ return value # String, return as-is
108
+
109
+
110
+ def load_env_config() -> dict[str, dict[str, Any]]:
111
+ """Load configuration from environment variables.
112
+
113
+ Reads all OASR_* environment variables and converts them to a nested
114
+ dictionary structure matching the config file format.
115
+
116
+ Returns:
117
+ Nested dictionary with config values from environment variables
118
+ Example: {"agent": {"default": "codex"}, "oasr": {"default_profile": "safe"}}
119
+
120
+ Notes:
121
+ - Only processes variables defined in ENV_VAR_MAP
122
+ - Silently skips variables with invalid values (logs warning)
123
+ - Returns empty sections if no relevant env vars set
124
+ """
125
+ config = {}
126
+
127
+ for env_var, (section, key) in ENV_VAR_MAP.items():
128
+ value = os.getenv(env_var)
129
+ if value is None:
130
+ continue
131
+
132
+ # Determine expected type based on key
133
+ # This is a heuristic - we infer type from key name
134
+ expected_type = str # Default
135
+ if key == "strict":
136
+ expected_type = bool
137
+ elif key == "reference_max_lines":
138
+ expected_type = int
139
+ elif key == "default_targets":
140
+ expected_type = list
141
+
142
+ try:
143
+ parsed_value = parse_value(value, expected_type)
144
+
145
+ # Create section if it doesn't exist
146
+ if section not in config:
147
+ config[section] = {}
148
+
149
+ config[section][key] = parsed_value
150
+
151
+ except (ValueError, TypeError) as e:
152
+ # Log warning but continue (fail-safe)
153
+ import sys
154
+
155
+ print(
156
+ f"⚠ Warning: Invalid value for {env_var}='{value}': {e}. Skipping.",
157
+ file=sys.stderr,
158
+ )
159
+ continue
160
+
161
+ return config
162
+
163
+
164
+ def merge_configs(
165
+ cli_overrides: dict[str, Any],
166
+ env_config: dict[str, dict[str, Any]],
167
+ file_config: dict[str, dict[str, Any]],
168
+ defaults: dict[str, dict[str, Any]],
169
+ ) -> dict[str, dict[str, Any]]:
170
+ """Merge configurations from multiple sources with correct precedence.
171
+
172
+ Precedence order (highest to lowest):
173
+ 1. cli_overrides - explicit CLI flags
174
+ 2. env_config - environment variables
175
+ 3. file_config - config file values
176
+ 4. defaults - built-in defaults
177
+
178
+ Args:
179
+ cli_overrides: Values explicitly set via CLI flags
180
+ env_config: Values from environment variables
181
+ file_config: Values from config file
182
+ defaults: Built-in default values
183
+
184
+ Returns:
185
+ Merged configuration dictionary
186
+
187
+ Notes:
188
+ - CLI overrides take precedence over everything
189
+ - Environment variables override config file
190
+ - Config file overrides defaults
191
+ - Sections are merged independently
192
+ """
193
+ result = {}
194
+
195
+ # Get all sections from all sources
196
+ all_sections = set()
197
+ for config in [defaults, file_config, env_config, cli_overrides]:
198
+ all_sections.update(config.keys())
199
+
200
+ # Merge each section with precedence
201
+ for section in all_sections:
202
+ result[section] = {}
203
+
204
+ # Start with defaults
205
+ if section in defaults:
206
+ result[section].update(defaults[section])
207
+
208
+ # Override with file config
209
+ if section in file_config:
210
+ result[section].update(file_config[section])
211
+
212
+ # Override with env config
213
+ if section in env_config:
214
+ result[section].update(env_config[section])
215
+
216
+ # Override with CLI (if present)
217
+ if section in cli_overrides:
218
+ result[section].update(cli_overrides[section])
219
+
220
+ return result
221
+
222
+
223
+ def get_config_source(
224
+ section: str,
225
+ key: str,
226
+ cli_overrides: dict[str, Any],
227
+ env_config: dict[str, dict[str, Any]],
228
+ file_config: dict[str, dict[str, Any]],
229
+ ) -> str:
230
+ """Determine the source of a config value.
231
+
232
+ Args:
233
+ section: Config section name
234
+ key: Config key name
235
+ cli_overrides: CLI flag overrides
236
+ env_config: Environment variable config
237
+ file_config: Config file values
238
+
239
+ Returns:
240
+ Source string: "cli flag", "env var", "config file", or "default"
241
+ """
242
+ if section in cli_overrides and key in cli_overrides[section]:
243
+ return "cli flag"
244
+ if section in env_config and key in env_config.get(section, {}):
245
+ return "env var"
246
+ if section in file_config and key in file_config.get(section, {}):
247
+ return "config file"
248
+ return "default"
config/schema.py CHANGED
@@ -5,6 +5,44 @@ from typing import Any
5
5
  VALID_AGENTS = {"codex", "copilot", "claude", "opencode"}
6
6
 
7
7
 
8
+ def validate_agent(agent: str | None) -> tuple[bool, str | None]:
9
+ """Validate agent configuration value.
10
+
11
+ Args:
12
+ agent: Agent name to validate
13
+
14
+ Returns:
15
+ Tuple of (is_valid, error_message)
16
+ """
17
+ if agent is None:
18
+ return (True, None)
19
+
20
+ if agent not in VALID_AGENTS:
21
+ sorted_agents = ", ".join(sorted(VALID_AGENTS))
22
+ return (False, f"Invalid agent '{agent}'. Valid agents: {sorted_agents}")
23
+
24
+ return (True, None)
25
+
26
+
27
+ def validate_profile_reference(profile_name: str, config: dict[str, Any]) -> tuple[bool, str | None]:
28
+ """Validate that a profile reference exists in config.
29
+
30
+ Args:
31
+ profile_name: Profile name to validate
32
+ config: Full config dictionary
33
+
34
+ Returns:
35
+ Tuple of (is_valid, error_message)
36
+ """
37
+ profiles = config.get("profiles", {})
38
+
39
+ if profile_name not in profiles:
40
+ available = ", ".join(sorted(profiles.keys()))
41
+ return (False, f"Profile '{profile_name}' not found. Available profiles: {available}")
42
+
43
+ return (True, None)
44
+
45
+
8
46
  def validate_config(config: dict[str, Any]) -> None:
9
47
  """Validate configuration dictionary.
10
48
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: oasr
3
- Version: 0.5.0
3
+ Version: 0.5.1
4
4
  Summary: CLI for managing agent skills across IDE integrations
5
5
  Project-URL: Homepage, https://github.com/jgodau/asr
6
6
  Project-URL: Repository, https://github.com/jgodau/asr
@@ -1,7 +1,7 @@
1
1
  __init__.py,sha256=cYuwXNht5J2GDPEbHz57rmXRyWzaUgAaCXz8okR0rKE,84
2
2
  __main__.py,sha256=Due_Us-4KNlLZhf8MkmoP1hWS5qMWmpZvz2ZaCqPHT4,120
3
3
  adapter.py,sha256=WEpYkKDTb7We0zU9i6Z-r5ydtUdghNhxTZ5Eq58h4fU,10027
4
- cli.py,sha256=r5LsYxPe5-y1sqAg-IrII3J5Cf7Y2z3KyICkyaI0U-U,2672
4
+ cli.py,sha256=xghN20mgfEeh3vR_Vaiv0i2f1MBN6gk8J0uU3kXRK8g,2672
5
5
  discovery.py,sha256=WWF8SN2LH88mOUBJLavM7rvXcxi6uDQGpqRK20GysxA,3298
6
6
  manifest.py,sha256=feNCjkFWfhoVubevKjLtKoIEuzT1YGQn6wWgs9XM8_o,12229
7
7
  registry.py,sha256=zGutwVP39xaYqc3KDEXMWCV1tORYpqc5JISO8OaWP1Q,4470
@@ -27,9 +27,9 @@ commands/adapter.py,sha256=_68v3t-dRU0mszzL4udKs1bKennyg7RfBTaK2fDGTsE,3215
27
27
  commands/add.py,sha256=NJLQ-8-3zy7o6S9VLfL_wauP-Vz0oNGwN3nvtiwxNYM,15255
28
28
  commands/clean.py,sha256=RQBAfe6iCLsjMqUyVR55JdYX9MBqgrUuIrA8rFKs1J0,1102
29
29
  commands/clone.py,sha256=4APH34-yHjiXQIQwBnKOSEQ_sxV24_GKypcOJMfncvs,5912
30
- commands/config.py,sha256=PKuOX7CPRAy2j5NG1rhHYDFJT1XvZnOTF2qJW04v34Q,4940
30
+ commands/config.py,sha256=4kzDEjVpwrmMPK_DPYePdQe2lGh_b8waYORZDHCDYZw,6976
31
31
  commands/diff.py,sha256=37JMjvfAEfvK7-4X5iFbD-IGkS8ae4YSY7ZDIZF5B9E,5766
32
- commands/exec.py,sha256=Su5IVQCUR2oKktFG4gCRA4A15-4-WTaCHpqRLONTnnY,8230
32
+ commands/exec.py,sha256=zFmxxclpHQF39sqDpR5436XQiEYo334BGcQ5a8gbR9I,8711
33
33
  commands/find.py,sha256=zgqwUnaG5aLX6gJIU2ZeQzxsFh2s7oDNNtmV-e-62Jg,1663
34
34
  commands/help.py,sha256=5yhIpgGs1xPs2f39lg-ELE7D0tV_uUTjxQsgkWusIwo,1449
35
35
  commands/info.py,sha256=zywaUQsrvcPXcX8W49P7Jqnr90pX8nBPqnH1XcIs0Uk,4396
@@ -41,9 +41,10 @@ commands/sync.py,sha256=ZQoB5hBqrzvM6LUQVlKqHQVJib4dB5qe5M-pVG2vtGM,4946
41
41
  commands/update.py,sha256=bOWjdTNyeYg-hvXv5GfUzEtsTA7gU9JLM592GI9Oq68,11939
42
42
  commands/use.py,sha256=ggB28g2BDg3Lv3nF40wnDAJ7p0mo6C1pc1KgahvQYXM,1452
43
43
  commands/validate.py,sha256=Y8TLHxW4Z98onmzu-h-kDIET-48lVaIdQXOvuyBemLw,2361
44
- config/__init__.py,sha256=kll8gcMJX9qn3Y4WJCieFP4hUdioe_RXGqEU1zFjOPI,3473
44
+ config/__init__.py,sha256=glSjT1_y4aOfhZ8odrUWCGF1hBbY_huTjVp6suepHDY,3647
45
45
  config/defaults.py,sha256=JfCltQYoE7EqBYlxsNrSITLmwifTvRrJe5lqL0Ys7Cs,986
46
- config/schema.py,sha256=7nXgT4m_k04VZl3XJF_v8W4YMwSFGoCqQMLZAOdLuKk,3445
46
+ config/env.py,sha256=WgnQXjhfvV7m1oxZCK9WdIX_rqLy_-BOSuPjbpjdI1c,7163
47
+ config/schema.py,sha256=VlvmiYWjU2hExBJfME90Oyqp-H4OHcUs_hvvp54K9jA,4498
47
48
  policy/__init__.py,sha256=0sPJaruOyc9ioNyIcrTW72RgpaE64FgibS0h5mQELb8,1353
48
49
  policy/defaults.py,sha256=9GMQM2l2OKTmhXlKwyTfcICR5vD9qEvyvqaR5KrN7ZI,620
49
50
  policy/enforcement.py,sha256=djsosjjfdyr0SjnHF2kz4u3glvMNgd1CJztN6yZE-fM,2749
@@ -51,9 +52,9 @@ policy/profile.py,sha256=WDKaUagsWnBPGz5a_OOcxTsdZ66WjaIaR0R7ITVqy8g,6790
51
52
  skillcopy/__init__.py,sha256=YUglUkDzKfnCt4ar_DU33ksI9fGyn2UYbV7qn2c_BcU,2322
52
53
  skillcopy/local.py,sha256=QH6484dCenjg8pfNOyTRbQQBklEWhkkTnfQok5ssf_4,1049
53
54
  skillcopy/remote.py,sha256=83jRA2VfjtSDGO-YM1x3WGJjKvWzK1RmSTL7SdUOz8s,3155
54
- oasr-0.5.0.dist-info/METADATA,sha256=rSs47OQ6xzJsAGud17O43UTi0WF6ZLCKlE6_MK-ROaE,17924
55
- oasr-0.5.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
56
- oasr-0.5.0.dist-info/entry_points.txt,sha256=VnMuOi6XYMbzAD2bP0X5uV1sQXjOqoDWJ33Lsxwq8u8,52
57
- oasr-0.5.0.dist-info/licenses/LICENSE,sha256=nQ1j9Ldb8FlJ-z7y2WuXPIlyfnYC7YPasjGdOBgcfP4,10561
58
- oasr-0.5.0.dist-info/licenses/NOTICE,sha256=EsfkCN0ZRDS0oj3ADvMKeKrAXaPlC8YfpSjvjGVv9jE,207
59
- oasr-0.5.0.dist-info/RECORD,,
55
+ oasr-0.5.1.dist-info/METADATA,sha256=fAfdWjbFnZGfRpQ7gJx1IgpKLbaXgpFZz6ddjdzumxc,17924
56
+ oasr-0.5.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
57
+ oasr-0.5.1.dist-info/entry_points.txt,sha256=VnMuOi6XYMbzAD2bP0X5uV1sQXjOqoDWJ33Lsxwq8u8,52
58
+ oasr-0.5.1.dist-info/licenses/LICENSE,sha256=nQ1j9Ldb8FlJ-z7y2WuXPIlyfnYC7YPasjGdOBgcfP4,10561
59
+ oasr-0.5.1.dist-info/licenses/NOTICE,sha256=EsfkCN0ZRDS0oj3ADvMKeKrAXaPlC8YfpSjvjGVv9jE,207
60
+ oasr-0.5.1.dist-info/RECORD,,
File without changes