Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.3.5
1.3.6
64 changes: 62 additions & 2 deletions mlc/script_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -501,10 +501,10 @@ def remote_run(self, run_args):

def run(self, run_args):
"""
####################################################################################################################
################################################################################
Target: Script
Action: Run
####################################################################################################################
################################################################################

The `run` action executes a script from an MLC repository.

Expand All @@ -518,12 +518,72 @@ def run(self, run_args):
1. -j: Displays the output in JSON format.
2. Instead of using `mlc run script --tags=`, you can simply use `mlcr`.
3. *<Individual script inputs>: The `mlcr` command can accept additional inputs defined in the script's `input_mappings` metadata.
4. --mlc_isolate: Run in an isolated temporary directory with a fresh MLC_REPOS.
5. --mlc_isolate_dir: Base directory for isolation (default: system temp dir).
6. --mlc_isolate_clean: Auto-remove the isolated directory after the run.

"""
if not run_args.get('tags') and not run_args.get('details'):
return self.call_script_module_function("help", run_args)

if str(run_args.get('mlc_isolate', '')).lower() in ('true', 'yes', '1'):
return self._run_isolated(run_args)

return self.call_script_module_function("run", run_args)

def _run_isolated(self, run_args):
"""Run a script in an isolated temporary directory with a fresh MLC_REPOS."""
import tempfile
import uuid
import shutil

isolate_dir = run_args.get('mlc_isolate_dir', '')
isolate_clean = str(run_args.get('mlc_isolate_clean', '')).lower() in ('true', 'yes', '1')
uid = uuid.uuid4().hex[:16]

if isolate_dir:
base = os.path.abspath(isolate_dir)
if not os.path.isdir(base):
return {'return': 1, 'error': f'mlc_isolate_dir does not exist: {base}'}
tmp_dir = os.path.join(base, f'mlcflow-isolated-{uid}')
else:
tmp_dir = os.path.join(tempfile.gettempdir(), f'mlcflow-isolated-{uid}')

os.makedirs(tmp_dir, exist_ok=True)
logger.info(f"Isolated run directory: {tmp_dir}")

orig_dir = os.getcwd()
orig_repos = os.environ.get('MLC_REPOS')
original_state = dict(self.__dict__)

try:
os.chdir(tmp_dir)
os.environ['MLC_REPOS'] = os.path.join(tmp_dir, 'MLC')

# Re-initialize parent with new MLC_REPOS so index/repos are fresh
from .action import Action
new_parent = Action()
self.__dict__.update(vars(new_parent))
self.parent = new_parent

result = self.call_script_module_function("run", run_args)
finally:
self.__dict__.clear()
self.__dict__.update(original_state)
os.chdir(orig_dir)
if orig_repos is not None:
os.environ['MLC_REPOS'] = orig_repos
elif 'MLC_REPOS' in os.environ:
del os.environ['MLC_REPOS']

if isolate_clean:
logger.info(f"Cleaning up isolated directory: {tmp_dir}")
shutil.rmtree(tmp_dir, ignore_errors=True)
else:
logger.info(f"Isolated run artifacts preserved at: {tmp_dir}")

return result

def test(self, run_args):
"""
####################################################################################################################
Expand Down
Loading