ry-tool 1.0.1__py3-none-any.whl → 1.2.0__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.
- ry_tool/executor.py +40 -5
- ry_tool/loader.py +3 -1
- ry_tool/parser.py +8 -0
- {ry_tool-1.0.1.dist-info → ry_tool-1.2.0.dist-info}/METADATA +1 -1
- {ry_tool-1.0.1.dist-info → ry_tool-1.2.0.dist-info}/RECORD +7 -7
- {ry_tool-1.0.1.dist-info → ry_tool-1.2.0.dist-info}/WHEEL +0 -0
- {ry_tool-1.0.1.dist-info → ry_tool-1.2.0.dist-info}/entry_points.txt +0 -0
ry_tool/executor.py
CHANGED
@@ -9,9 +9,12 @@ import subprocess
|
|
9
9
|
import sys
|
10
10
|
import os
|
11
11
|
import json
|
12
|
+
import yaml
|
12
13
|
from typing import Dict, Any, List, Optional
|
13
14
|
from dataclasses import dataclass
|
14
15
|
from io import StringIO
|
16
|
+
from pathlib import Path
|
17
|
+
import ry_tool.utils # Import ry_tool modules
|
15
18
|
|
16
19
|
|
17
20
|
@dataclass
|
@@ -59,17 +62,19 @@ class Executor:
|
|
59
62
|
Returns:
|
60
63
|
ExecutionResult
|
61
64
|
"""
|
62
|
-
# Merge environment
|
63
|
-
env =
|
65
|
+
# Merge environment - extra_env takes precedence
|
66
|
+
env = {}
|
64
67
|
if extra_env:
|
65
68
|
env.update(extra_env)
|
69
|
+
if step.get('env'):
|
70
|
+
env.update(step['env'])
|
66
71
|
|
67
72
|
if 'shell' in step:
|
68
73
|
return self.execute_shell(step['shell'], env,
|
69
74
|
interactive=step.get('interactive', False),
|
70
75
|
capture_file=step.get('_capture_file'))
|
71
76
|
elif 'python' in step:
|
72
|
-
return self.execute_python(step['python'])
|
77
|
+
return self.execute_python(step['python'], extra_env=env)
|
73
78
|
elif 'subprocess' in step:
|
74
79
|
return self.execute_subprocess(step['subprocess'])
|
75
80
|
elif 'ruby' in step:
|
@@ -203,7 +208,7 @@ class Executor:
|
|
203
208
|
returncode=1
|
204
209
|
)
|
205
210
|
|
206
|
-
def execute_python(self, code: str) -> ExecutionResult:
|
211
|
+
def execute_python(self, code: str, extra_env: Dict[str, str] = None) -> ExecutionResult:
|
207
212
|
"""
|
208
213
|
Execute Python code with context.
|
209
214
|
|
@@ -230,15 +235,45 @@ class Executor:
|
|
230
235
|
original_env = safe_copy(self.context.get('env'), {})
|
231
236
|
original_captured = safe_copy(self.context.get('captured'), {})
|
232
237
|
|
238
|
+
# Set up Python path from environment
|
239
|
+
# This allows library code to import from lib/ directories
|
240
|
+
if extra_env and 'PYTHONPATH' in extra_env:
|
241
|
+
for path in extra_env['PYTHONPATH'].split(':'):
|
242
|
+
if path and path not in sys.path:
|
243
|
+
sys.path.insert(0, path)
|
244
|
+
|
245
|
+
# Also add library directory if provided
|
246
|
+
if extra_env and 'RY_LIBRARY_DIR' in extra_env:
|
247
|
+
lib_path = os.path.join(extra_env['RY_LIBRARY_DIR'], 'lib')
|
248
|
+
if os.path.exists(lib_path) and lib_path not in sys.path:
|
249
|
+
sys.path.insert(0, lib_path)
|
250
|
+
|
251
|
+
# Add all sibling library lib/ directories for cross-library imports
|
252
|
+
# This allows e.g., uv library to import from git library
|
253
|
+
libraries_root = os.path.dirname(extra_env['RY_LIBRARY_DIR'])
|
254
|
+
if os.path.exists(libraries_root):
|
255
|
+
for item in os.listdir(libraries_root):
|
256
|
+
sibling_lib = os.path.join(libraries_root, item, 'lib')
|
257
|
+
if os.path.isdir(sibling_lib) and sibling_lib not in sys.path:
|
258
|
+
sys.path.insert(0, sibling_lib)
|
259
|
+
|
260
|
+
# Merge environment variables into env dict
|
261
|
+
merged_env = safe_copy(self.context.get('env'), {})
|
262
|
+
if extra_env:
|
263
|
+
merged_env.update(extra_env)
|
264
|
+
|
233
265
|
# Prepare execution environment with mutable references
|
234
266
|
exec_globals = {
|
235
267
|
'sys': sys,
|
236
268
|
'os': os,
|
237
269
|
'subprocess': subprocess,
|
238
270
|
'json': json,
|
271
|
+
'yaml': yaml,
|
272
|
+
'Path': Path,
|
273
|
+
'ry_tool': ry_tool, # Make ry_tool module available
|
239
274
|
'flags': safe_copy(self.context.get('flags'), {}),
|
240
275
|
'arguments': safe_copy(self.context.get('arguments'), {}),
|
241
|
-
'env':
|
276
|
+
'env': merged_env,
|
242
277
|
'captured': safe_copy(self.context.get('captured'), {}),
|
243
278
|
'remaining_args': self.context.get('remaining_args', []),
|
244
279
|
'positionals': safe_copy(self.context.get('positionals'), []),
|
ry_tool/loader.py
CHANGED
@@ -22,6 +22,7 @@ class LibraryConfig:
|
|
22
22
|
commands: Dict[str, Any] = field(default_factory=dict)
|
23
23
|
metadata: Dict[str, Any] = field(default_factory=dict)
|
24
24
|
path: Optional[Path] = None
|
25
|
+
workflows: List[str] = field(default_factory=list) # Common workflow examples
|
25
26
|
|
26
27
|
|
27
28
|
class LibraryLoader:
|
@@ -179,7 +180,8 @@ class LibraryLoader:
|
|
179
180
|
description=data.get('description', ''),
|
180
181
|
commands=commands,
|
181
182
|
metadata=metadata,
|
182
|
-
path=path
|
183
|
+
path=path,
|
184
|
+
workflows=data.get('workflows', [])
|
183
185
|
)
|
184
186
|
|
185
187
|
def _validate_command(self, name: str, config: Dict[str, Any]):
|
ry_tool/parser.py
CHANGED
@@ -240,6 +240,14 @@ class CommandParser:
|
|
240
240
|
if cmd_name != '*': # Skip catch-all
|
241
241
|
desc = cmd_config.get('description', 'No description')
|
242
242
|
help_lines.append(f" {cmd_name:<15} {desc}")
|
243
|
+
|
244
|
+
# Add common workflows if defined
|
245
|
+
if hasattr(library_config, 'workflows') and library_config.workflows:
|
246
|
+
help_lines.append("")
|
247
|
+
help_lines.append("Common workflow:")
|
248
|
+
for workflow in library_config.workflows:
|
249
|
+
help_lines.append(f" {workflow}")
|
250
|
+
|
243
251
|
help_lines.append("")
|
244
252
|
help_lines.append("Use: ry-next <library> <command> --help for command details")
|
245
253
|
|
@@ -3,14 +3,14 @@ ry_tool/__main__.py,sha256=fbQGeI2WWTZrLUI7LToOfAV5JckzB_El64i0zjqOouI,138
|
|
3
3
|
ry_tool/_cli.py,sha256=8gZ-c1FlerAZ5e0K4v7Mv2GafMLiGAcv-3ET8oHmMdQ,7693
|
4
4
|
ry_tool/app.py,sha256=TjMCQDZ5QkqKiAqUViGe84T6d6Deb67jnRRFAmEk15w,15997
|
5
5
|
ry_tool/context.py,sha256=elDiqty6Fssq-74ra8twtzKfolQ154xLj2ECwZbzcy4,9743
|
6
|
-
ry_tool/executor.py,sha256=
|
6
|
+
ry_tool/executor.py,sha256=hQOnL9Ii_scsFtOzLOE1MfYA5_fDbq2H9ATsBcGymc0,18867
|
7
7
|
ry_tool/installer.py,sha256=cFnEROvpfIjMkpZF4AzRU4bHDNneJBMk5gRXP5jJgqE,5712
|
8
|
-
ry_tool/loader.py,sha256=
|
8
|
+
ry_tool/loader.py,sha256=fPdfrYvqV4c2yWrlxuOU8ODaHkiADVkFwjMG0M2pznA,9941
|
9
9
|
ry_tool/matcher.py,sha256=fg857FoF2CjLsUvJl2vaeRHHHGx6A8vraI1fnddOKN4,7458
|
10
|
-
ry_tool/parser.py,sha256=
|
10
|
+
ry_tool/parser.py,sha256=TfYCUxWKGroJ9cgBaXLTVqXZT1hzble6OD3wHL4zpig,9644
|
11
11
|
ry_tool/template.py,sha256=uEvc70vA7NZ3qKemsddTnYFKhdc2sEf-5uytd2wPiBk,10094
|
12
12
|
ry_tool/utils.py,sha256=TpJz7DSkyJewzyDPUsQXI9awDgMbE6nC__DRbUYNQpw,13762
|
13
|
-
ry_tool-1.0.
|
14
|
-
ry_tool-1.0.
|
15
|
-
ry_tool-1.0.
|
16
|
-
ry_tool-1.0.
|
13
|
+
ry_tool-1.2.0.dist-info/WHEEL,sha256=Jb20R3Ili4n9P1fcwuLup21eQ5r9WXhs4_qy7VTrgPI,79
|
14
|
+
ry_tool-1.2.0.dist-info/entry_points.txt,sha256=z2YdpRoOA9Kk0Sg26A6Eu6PrwdJLQ22dxdZqHnhWYNo,45
|
15
|
+
ry_tool-1.2.0.dist-info/METADATA,sha256=t0BxXiN55bJcc373a733cmvJ3riyXSNa4_1UEGoi4vM,2612
|
16
|
+
ry_tool-1.2.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|