h
This commit is contained in:
@@ -1,9 +0,0 @@
|
|||||||
"""Top-level package for Medeia-Macina.
|
|
||||||
|
|
||||||
This package provides the `cli_entry` module which exposes the `main()` entry
|
|
||||||
point used by command-line launchers.
|
|
||||||
"""
|
|
||||||
|
|
||||||
__all__ = ["cli_entry"]
|
|
||||||
|
|
||||||
__version__ = "0.1.0"
|
|
||||||
@@ -1,276 +0,0 @@
|
|||||||
"""Packaged CLI entrypoint used by installers and console scripts.
|
|
||||||
|
|
||||||
This module provides the `main` entrypoint for `mm`/`medeia` and supports
|
|
||||||
running from a development checkout (by importing the top-level
|
|
||||||
`CLI.MedeiaCLI`) or when running tests that inject a legacy
|
|
||||||
`medeia_entry` shim into `sys.modules`.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from typing import Optional, List, Tuple
|
|
||||||
import sys
|
|
||||||
import importlib
|
|
||||||
from pathlib import Path
|
|
||||||
import shlex
|
|
||||||
|
|
||||||
|
|
||||||
def _ensure_repo_root_on_sys_path(pkg_file: Optional[Path] = None) -> None:
|
|
||||||
"""Ensure the repository root (where top-level modules live) is importable.
|
|
||||||
|
|
||||||
The project currently keeps key modules like `CLI.py` at the repo root.
|
|
||||||
When `mm` is invoked from a different working directory, that repo root is
|
|
||||||
not necessarily on `sys.path`, which breaks `import CLI`.
|
|
||||||
|
|
||||||
We infer the repo root by walking up from this package location and looking
|
|
||||||
for a sibling `CLI.py`.
|
|
||||||
|
|
||||||
`pkg_file` exists for unit tests; production uses this module's `__file__`.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
pkg_dir = (pkg_file or Path(__file__)).resolve().parent
|
|
||||||
except Exception:
|
|
||||||
return
|
|
||||||
|
|
||||||
for parent in pkg_dir.parents:
|
|
||||||
try:
|
|
||||||
if (parent / "CLI.py").exists():
|
|
||||||
parent_str = str(parent)
|
|
||||||
if parent_str not in sys.path:
|
|
||||||
sys.path.insert(0, parent_str)
|
|
||||||
return
|
|
||||||
except Exception:
|
|
||||||
continue
|
|
||||||
|
|
||||||
|
|
||||||
def _parse_mode_and_strip_args(args: List[str]) -> Tuple[Optional[str], List[str]]:
|
|
||||||
"""Parse --gui/--cli/--mode flags and return (mode, cleaned_args).
|
|
||||||
|
|
||||||
The function removes any mode flags from the argument list so the selected
|
|
||||||
runner can receive the remaining arguments untouched.
|
|
||||||
|
|
||||||
Supported forms:
|
|
||||||
--gui, -g, --gui=true
|
|
||||||
--cli, -c, --cli=true
|
|
||||||
--mode=gui|cli
|
|
||||||
--mode gui|cli
|
|
||||||
|
|
||||||
Raises ValueError on conflicting or invalid flags.
|
|
||||||
"""
|
|
||||||
mode: Optional[str] = None
|
|
||||||
out: List[str] = []
|
|
||||||
i = 0
|
|
||||||
while i < len(args):
|
|
||||||
a = args[i]
|
|
||||||
la = a.lower()
|
|
||||||
|
|
||||||
# --gui / -g
|
|
||||||
if la in ("--gui", "-g"):
|
|
||||||
if mode and mode != "gui":
|
|
||||||
raise ValueError("Conflicting mode flags: found both 'gui' and 'cli'")
|
|
||||||
mode = "gui"
|
|
||||||
i += 1
|
|
||||||
continue
|
|
||||||
if la.startswith("--gui="):
|
|
||||||
val = la.split("=", 1)[1]
|
|
||||||
if val and val not in ("0", "false", "no", "off"):
|
|
||||||
if mode and mode != "gui":
|
|
||||||
raise ValueError(
|
|
||||||
"Conflicting mode flags: found both 'gui' and 'cli'"
|
|
||||||
)
|
|
||||||
mode = "gui"
|
|
||||||
i += 1
|
|
||||||
continue
|
|
||||||
|
|
||||||
# --cli / -c
|
|
||||||
if la in ("--cli", "-c"):
|
|
||||||
if mode and mode != "cli":
|
|
||||||
raise ValueError("Conflicting mode flags: found both 'gui' and 'cli'")
|
|
||||||
mode = "cli"
|
|
||||||
i += 1
|
|
||||||
continue
|
|
||||||
if la.startswith("--cli="):
|
|
||||||
val = la.split("=", 1)[1]
|
|
||||||
if val and val not in ("0", "false", "no", "off"):
|
|
||||||
if mode and mode != "cli":
|
|
||||||
raise ValueError(
|
|
||||||
"Conflicting mode flags: found both 'gui' and 'cli'"
|
|
||||||
)
|
|
||||||
mode = "cli"
|
|
||||||
i += 1
|
|
||||||
continue
|
|
||||||
|
|
||||||
# --mode
|
|
||||||
if la.startswith("--mode="):
|
|
||||||
val = la.split("=", 1)[1]
|
|
||||||
val = val.lower()
|
|
||||||
if val not in ("gui", "cli"):
|
|
||||||
raise ValueError("--mode must be 'gui' or 'cli'")
|
|
||||||
if mode and mode != val:
|
|
||||||
raise ValueError("Conflicting mode flags: found both 'gui' and 'cli'")
|
|
||||||
mode = val
|
|
||||||
i += 1
|
|
||||||
continue
|
|
||||||
if la == "--mode":
|
|
||||||
if i + 1 >= len(args):
|
|
||||||
raise ValueError("--mode requires a value ('gui' or 'cli')")
|
|
||||||
val = args[i + 1].lower()
|
|
||||||
if val not in ("gui", "cli"):
|
|
||||||
raise ValueError("--mode must be 'gui' or 'cli'")
|
|
||||||
if mode and mode != val:
|
|
||||||
raise ValueError("Conflicting mode flags: found both 'gui' and 'cli'")
|
|
||||||
mode = val
|
|
||||||
i += 2
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Not a mode flag; keep it
|
|
||||||
out.append(a)
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
return mode, out
|
|
||||||
|
|
||||||
|
|
||||||
def _run_cli(clean_args: List[str]) -> int:
|
|
||||||
"""Run the CLI runner (MedeiaCLI) with cleaned argv list.
|
|
||||||
|
|
||||||
The function supports three modes (in order):
|
|
||||||
1) If a `medeia_entry` module is present in sys.modules (for tests/legacy
|
|
||||||
scenarios), use it as the source of `MedeiaCLI`.
|
|
||||||
2) If running from a development checkout, import the top-level `CLI` and
|
|
||||||
use `MedeiaCLI` from there.
|
|
||||||
3) Otherwise fail with a helpful message suggesting an editable install.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
sys.argv[1:] = list(clean_args)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# 1) Check for an in-memory 'medeia_entry' module (tests/legacy installs)
|
|
||||||
MedeiaCLI = None
|
|
||||||
if "medeia_entry" in sys.modules:
|
|
||||||
mod = sys.modules.get("medeia_entry")
|
|
||||||
if hasattr(mod, "MedeiaCLI"):
|
|
||||||
MedeiaCLI = getattr(mod, "MedeiaCLI")
|
|
||||||
else:
|
|
||||||
# Preserve the existing error message used by tests that inject a
|
|
||||||
# dummy 'medeia_entry' without a `MedeiaCLI` attribute.
|
|
||||||
raise ImportError(
|
|
||||||
"Imported module 'medeia_entry' does not define 'MedeiaCLI' and direct import of top-level 'CLI' failed.\n"
|
|
||||||
"Remedy: ensure the top-level 'medeia_entry' module exports 'MedeiaCLI' or run from the project root/debug the checkout."
|
|
||||||
)
|
|
||||||
|
|
||||||
# 2) If no in-memory module provided the class, try importing the repo-root CLI
|
|
||||||
if MedeiaCLI is None:
|
|
||||||
try:
|
|
||||||
_ensure_repo_root_on_sys_path()
|
|
||||||
from CLI import MedeiaCLI as _M # type: ignore
|
|
||||||
MedeiaCLI = _M
|
|
||||||
except Exception:
|
|
||||||
raise ImportError(
|
|
||||||
"Could not import 'MedeiaCLI'. This often means the project is not available on sys.path (run 'pip install -e scripts' or re-run the bootstrap script)."
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
|
||||||
app = MedeiaCLI()
|
|
||||||
app.run()
|
|
||||||
return 0
|
|
||||||
except SystemExit as exc:
|
|
||||||
return int(getattr(exc, "code", 0) or 0)
|
|
||||||
|
|
||||||
|
|
||||||
def _run_gui(clean_args: List[str]) -> int:
|
|
||||||
"""Run the TUI runner (PipelineHubApp).
|
|
||||||
|
|
||||||
The TUI is imported lazily; if Textual or the TUI code is unavailable we
|
|
||||||
give a helpful error message and exit non‑zero.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
_ensure_repo_root_on_sys_path()
|
|
||||||
tui_mod = importlib.import_module("TUI.tui")
|
|
||||||
except Exception as exc:
|
|
||||||
print(
|
|
||||||
"Error: Unable to import TUI (Textual may not be installed):",
|
|
||||||
exc,
|
|
||||||
file=sys.stderr,
|
|
||||||
)
|
|
||||||
return 2
|
|
||||||
|
|
||||||
try:
|
|
||||||
PipelineHubApp = getattr(tui_mod, "PipelineHubApp")
|
|
||||||
except AttributeError:
|
|
||||||
print("Error: 'TUI.tui' does not expose 'PipelineHubApp'", file=sys.stderr)
|
|
||||||
return 2
|
|
||||||
|
|
||||||
try:
|
|
||||||
app = PipelineHubApp()
|
|
||||||
app.run()
|
|
||||||
return 0
|
|
||||||
except SystemExit as exc:
|
|
||||||
return int(getattr(exc, "code", 0) or 0)
|
|
||||||
|
|
||||||
|
|
||||||
def main(argv: Optional[List[str]] = None) -> int:
|
|
||||||
"""Entry point for console_scripts.
|
|
||||||
|
|
||||||
Accepts an optional argv list (useful for testing). Mode flags are parsed
|
|
||||||
and removed before dispatching to the selected runner.
|
|
||||||
"""
|
|
||||||
args = list(argv) if argv is not None else list(sys.argv[1:])
|
|
||||||
|
|
||||||
try:
|
|
||||||
mode, clean_args = _parse_mode_and_strip_args(args)
|
|
||||||
except ValueError as exc:
|
|
||||||
print(f"Error parsing mode flags: {exc}", file=sys.stderr)
|
|
||||||
return 2
|
|
||||||
|
|
||||||
# Early environment sanity check to detect urllib3/urllib3-future conflicts.
|
|
||||||
# When a broken urllib3 is detected we print an actionable message and
|
|
||||||
# exit early to avoid confusing import-time errors later during startup.
|
|
||||||
try:
|
|
||||||
from SYS.env_check import ensure_urllib3_ok
|
|
||||||
|
|
||||||
try:
|
|
||||||
ensure_urllib3_ok(exit_on_error=True)
|
|
||||||
except SystemExit as exc:
|
|
||||||
# Bubble out the exit code as the CLI return value for clearer
|
|
||||||
# behavior in shell sessions and scripts.
|
|
||||||
return int(getattr(exc, "code", 2) or 2)
|
|
||||||
except Exception:
|
|
||||||
# If the sanity check itself cannot be imported or run, don't block
|
|
||||||
# startup; we'll continue and let normal import errors surface.
|
|
||||||
pass
|
|
||||||
|
|
||||||
# If GUI requested, delegate directly (GUI may decide to honor any args itself)
|
|
||||||
if mode == "gui":
|
|
||||||
return _run_gui(clean_args)
|
|
||||||
|
|
||||||
# Support quoting a pipeline (or even a single full command) on the command line.
|
|
||||||
#
|
|
||||||
# - If the user provides a single argument that contains a pipe character,
|
|
||||||
# treat it as a pipeline and rewrite the args to call the internal `pipeline`
|
|
||||||
# subcommand so existing CLI pipeline handling is used.
|
|
||||||
#
|
|
||||||
# - If the user provides a single argument that contains whitespace but no pipe,
|
|
||||||
# expand it into argv tokens (PowerShell commonly encourages quoting strings).
|
|
||||||
#
|
|
||||||
# Examples:
|
|
||||||
# mm "download-media <url> | add-tag 'x' | add-file -store local"
|
|
||||||
# mm "download-media '<url>' -query 'format:720p' -path 'C:\\out'"
|
|
||||||
if len(clean_args) == 1:
|
|
||||||
single = clean_args[0]
|
|
||||||
if "|" in single and not single.startswith("-"):
|
|
||||||
clean_args = ["pipeline", "--pipeline", single]
|
|
||||||
elif (not single.startswith("-")) and any(ch.isspace() for ch in single):
|
|
||||||
try:
|
|
||||||
expanded = shlex.split(single, posix=True)
|
|
||||||
if expanded:
|
|
||||||
clean_args = list(expanded)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Default to CLI if --cli is requested or no explicit mode provided.
|
|
||||||
return _run_cli(clean_args)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
raise SystemExit(main())
|
|
||||||
1
scripts/__init__.py
Normal file
1
scripts/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
"""Minimal package marker for scripts-based entrypoints."""
|
||||||
@@ -226,8 +226,8 @@ if (-not $NoInstall) {
|
|||||||
# Verify top-level 'CLI' import and (if missing) attempt to make it available
|
# Verify top-level 'CLI' import and (if missing) attempt to make it available
|
||||||
Write-Log "Verifying installed CLI import..."
|
Write-Log "Verifying installed CLI import..."
|
||||||
try {
|
try {
|
||||||
& $venvPython -c "import importlib; importlib.import_module('medeia_macina.cli_entry')" 2>$null
|
& $venvPython -c "import importlib; importlib.import_module('scripts.cli_entry')" 2>$null
|
||||||
if ($LASTEXITCODE -eq 0) { Write-Log "OK: 'medeia_macina.cli_entry' is importable in the venv." }
|
if ($LASTEXITCODE -eq 0) { Write-Log "OK: 'scripts.cli_entry' is importable in the venv." }
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -493,7 +493,7 @@ if ($IsWindowsPlatform) {
|
|||||||
$target = $mmExe
|
$target = $mmExe
|
||||||
} else {
|
} else {
|
||||||
$target = $venvPython
|
$target = $venvPython
|
||||||
$args = "-m medeia_macina.cli_entry"
|
$args = "-m scripts.cli_entry"
|
||||||
}
|
}
|
||||||
if ($CreateDesktopShortcut) {
|
if ($CreateDesktopShortcut) {
|
||||||
$desk = [Environment]::GetFolderPath('Desktop')
|
$desk = [Environment]::GetFolderPath('Desktop')
|
||||||
@@ -545,10 +545,10 @@ if ($env:MM_DEBUG) {
|
|||||||
if (Test-Path $py) { & $py -c "import sys,importlib,importlib.util,traceback; print('sys.executable:', sys.executable); print('sys.path (first 8):', sys.path[:8]);" }
|
if (Test-Path $py) { & $py -c "import sys,importlib,importlib.util,traceback; print('sys.executable:', sys.executable); print('sys.path (first 8):', sys.path[:8]);" }
|
||||||
else { python -c "import sys,importlib,importlib.util,traceback; print('sys.executable:', sys.executable); print('sys.path (first 8):', sys.path[:8]);" }
|
else { python -c "import sys,importlib,importlib.util,traceback; print('sys.executable:', sys.executable); print('sys.path (first 8):', sys.path[:8]);" }
|
||||||
}
|
}
|
||||||
if (Test-Path $py) { & $py -m medeia_macina.cli_entry @args; exit $LASTEXITCODE }
|
if (Test-Path $py) { & $py -m scripts.cli_entry @args; exit $LASTEXITCODE }
|
||||||
if (Test-Path (Join-Path $repo 'CLI.py')) { & python (Join-Path $repo 'CLI.py') @args; exit $LASTEXITCODE }
|
if (Test-Path (Join-Path $repo 'CLI.py')) { & python (Join-Path $repo 'CLI.py') @args; exit $LASTEXITCODE }
|
||||||
# fallback
|
# fallback
|
||||||
python -m medeia_macina.cli_entry @args
|
python -m scripts.cli_entry @args
|
||||||
'@
|
'@
|
||||||
# Thin wrapper: prefer the canonical Python bootstrap installer
|
# Thin wrapper: prefer the canonical Python bootstrap installer
|
||||||
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||||
@@ -587,7 +587,7 @@ Write-Host 'Error: no suitable Python 3 interpreter found. Please install Python
|
|||||||
exit 127 # Inject the actual repo path safely (escape embedded double-quotes if any)
|
exit 127 # Inject the actual repo path safely (escape embedded double-quotes if any)
|
||||||
$ps1Text = $ps1Text.Replace('__REPO__', $repo.Replace('"', '""'))
|
$ps1Text = $ps1Text.Replace('__REPO__', $repo.Replace('"', '""'))
|
||||||
# Ensure the PowerShell shim falls back to the correct module when the venv isn't present
|
# Ensure the PowerShell shim falls back to the correct module when the venv isn't present
|
||||||
# (No legacy 'medeia_entry' shim - use the packaged entry 'medeia_macina.cli_entry')
|
# (No legacy 'medeia_entry' shim - use the packaged entry 'scripts.cli_entry')
|
||||||
if (Test-Path $mmPs1) {
|
if (Test-Path $mmPs1) {
|
||||||
$bak = "$mmPs1.bak$(Get-Date -UFormat %s)"
|
$bak = "$mmPs1.bak$(Get-Date -UFormat %s)"
|
||||||
Move-Item -Path $mmPs1 -Destination $bak -Force
|
Move-Item -Path $mmPs1 -Destination $bak -Force
|
||||||
@@ -626,7 +626,7 @@ Write-Host ""
|
|||||||
Write-Host "To run the app:"
|
Write-Host "To run the app:"
|
||||||
Write-Host " $ .\$VenvPath\Scripts\mm.exe (Windows) or"
|
Write-Host " $ .\$VenvPath\Scripts\mm.exe (Windows) or"
|
||||||
Write-Host " $ ./$VenvPath/bin/mm (Linux) or"
|
Write-Host " $ ./$VenvPath/bin/mm (Linux) or"
|
||||||
Write-Host " $ $venvPython -m medeia_macina.cli_entry"
|
Write-Host " $ $venvPython -m scripts.cli_entry"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "If the global 'mm' launcher fails, collect runtime diagnostics by setting MM_DEBUG and re-running the command:""
|
Write-Host "If the global 'mm' launcher fails, collect runtime diagnostics by setting MM_DEBUG and re-running the command:""
|
||||||
if ($IsWindowsPlatform) { Write-Host " PowerShell: $env:MM_DEBUG = '1'; mm" } else { Write-Host " POSIX: MM_DEBUG=1 mm" }
|
if ($IsWindowsPlatform) { Write-Host " PowerShell: $env:MM_DEBUG = '1'; mm" } else { Write-Host " POSIX: MM_DEBUG=1 mm" }
|
||||||
|
|||||||
@@ -800,10 +800,10 @@ $venvScripts = Join-Path $venv 'Scripts'
|
|||||||
if (Test-Path $venvScripts) { $env:PATH = $venvScripts + ';' + $env:PATH }
|
if (Test-Path $venvScripts) { $env:PATH = $venvScripts + ';' + $env:PATH }
|
||||||
$py = Join-Path $venv 'Scripts\python.exe'
|
$py = Join-Path $venv 'Scripts\python.exe'
|
||||||
$cli = Join-Path $repo 'CLI.py'
|
$cli = Join-Path $repo 'CLI.py'
|
||||||
if (Test-Path $py) { & $py -m medeia_macina.cli_entry @args; exit $LASTEXITCODE }
|
if (Test-Path $py) { & $py -m scripts.cli_entry @args; exit $LASTEXITCODE }
|
||||||
if (Test-Path $cli) { & python $cli @args; exit $LASTEXITCODE }
|
if (Test-Path $cli) { & python $cli @args; exit $LASTEXITCODE }
|
||||||
# fallback
|
# fallback
|
||||||
python -m medeia_macina.cli_entry @args
|
python -m scripts.cli_entry @args
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
ps1.write_text(ps1_text, encoding="utf-8")
|
ps1.write_text(ps1_text, encoding="utf-8")
|
||||||
@@ -836,9 +836,9 @@ python -m medeia_macina.cli_entry @args
|
|||||||
' Write-Host "MM_DEBUG: diagnostics" -ForegroundColor Yellow\n'
|
' Write-Host "MM_DEBUG: diagnostics" -ForegroundColor Yellow\n'
|
||||||
" & $py -c \"import sys,importlib,importlib.util,traceback; print('sys.executable:', sys.executable); print('sys.path (first 8):', sys.path[:8]);\"\n"
|
" & $py -c \"import sys,importlib,importlib.util,traceback; print('sys.executable:', sys.executable); print('sys.path (first 8):', sys.path[:8]);\"\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" & $py -m medeia_macina.cli_entry @args; exit $LASTEXITCODE\n"
|
" & $py -m scripts.cli_entry @args; exit $LASTEXITCODE\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"python -m medeia_macina.cli_entry @args\n"
|
"python -m scripts.cli_entry @args\n"
|
||||||
)
|
)
|
||||||
if mm_ps1.exists():
|
if mm_ps1.exists():
|
||||||
bak = mm_ps1.with_suffix(f".bak{int(time.time())}")
|
bak = mm_ps1.with_suffix(f".bak{int(time.time())}")
|
||||||
@@ -916,7 +916,7 @@ python -m medeia_macina.cli_entry @args
|
|||||||
' for pycmd in "$VENV/bin/python3" "$VENV/bin/python" "$(command -v python3 2>/dev/null)" "$(command -v python 2>/dev/null)"; do\n'
|
' for pycmd in "$VENV/bin/python3" "$VENV/bin/python" "$(command -v python3 2>/dev/null)" "$(command -v python 2>/dev/null)"; do\n'
|
||||||
' if [ -n "$pycmd" ] && [ -x "$pycmd" ]; then\n'
|
' if [ -n "$pycmd" ] && [ -x "$pycmd" ]; then\n'
|
||||||
' echo "---- Testing with: $pycmd ----" >&2\n'
|
' echo "---- Testing with: $pycmd ----" >&2\n'
|
||||||
" $pycmd - <<'PY'\nimport sys, importlib, traceback, importlib.util\nprint('sys.executable:', sys.executable)\nprint('sys.path (first 8):', sys.path[:8])\nfor mod in ('CLI','medeia_macina','medeia_macina.cli_entry'):\n try:\n spec = importlib.util.find_spec(mod)\n print(mod, 'spec:', spec)\n if spec:\n m = importlib.import_module(mod)\n print(mod, 'loaded at', getattr(m, '__file__', None))\n except Exception:\n print(mod, 'import failed')\n traceback.print_exc()\nPY\n"
|
" $pycmd - <<'PY'\nimport sys, importlib, traceback, importlib.util\nprint('sys.executable:', sys.executable)\nprint('sys.path (first 8):', sys.path[:8])\nfor mod in ('CLI','medeia_macina','scripts.cli_entry'):\n try:\n spec = importlib.util.find_spec(mod)\n print(mod, 'spec:', spec)\n if spec:\n m = importlib.import_module(mod)\n print(mod, 'loaded at', getattr(m, '__file__', None))\n except Exception:\n print(mod, 'import failed')\n traceback.print_exc()\nPY\n"
|
||||||
" fi\n"
|
" fi\n"
|
||||||
" done\n"
|
" done\n"
|
||||||
' echo "MM_DEBUG: end diagnostics" >&2\n'
|
' echo "MM_DEBUG: end diagnostics" >&2\n'
|
||||||
@@ -927,18 +927,18 @@ python -m medeia_macina.cli_entry @args
|
|||||||
"fi\n"
|
"fi\n"
|
||||||
"# Prefer venv's python3, then venv's python\n"
|
"# Prefer venv's python3, then venv's python\n"
|
||||||
'if [ -x "$VENV/bin/python3" ]; then\n'
|
'if [ -x "$VENV/bin/python3" ]; then\n'
|
||||||
' exec "$VENV/bin/python3" -m medeia_macina.cli_entry "$@"\n'
|
' exec "$VENV/bin/python3" -m scripts.cli_entry "$@"\n'
|
||||||
"fi\n"
|
"fi\n"
|
||||||
'if [ -x "$VENV/bin/python" ]; then\n'
|
'if [ -x "$VENV/bin/python" ]; then\n'
|
||||||
' exec "$VENV/bin/python" -m medeia_macina.cli_entry "$@"\n'
|
' exec "$VENV/bin/python" -m scripts.cli_entry "$@"\n'
|
||||||
"fi\n"
|
"fi\n"
|
||||||
"# Fallback to system python3, then system python (only if it's Python 3)\n"
|
"# Fallback to system python3, then system python (only if it's Python 3)\n"
|
||||||
"if command -v python3 >/dev/null 2>&1; then\n"
|
"if command -v python3 >/dev/null 2>&1; then\n"
|
||||||
' exec python3 -m medeia_macina.cli_entry "$@"\n'
|
' exec python3 -m scripts.cli_entry "$@"\n'
|
||||||
"fi\n"
|
"fi\n"
|
||||||
"if command -v python >/dev/null 2>&1; then\n"
|
"if command -v python >/dev/null 2>&1; then\n"
|
||||||
" if python -c 'import sys; sys.exit(0 if sys.version_info[0] >= 3 else 1)'; then\n"
|
" if python -c 'import sys; sys.exit(0 if sys.version_info[0] >= 3 else 1)'; then\n"
|
||||||
' exec python -m medeia_macina.cli_entry "$@"\n'
|
' exec python -m scripts.cli_entry "$@"\n'
|
||||||
" fi\n"
|
" fi\n"
|
||||||
"fi\n"
|
"fi\n"
|
||||||
"echo 'Error: no suitable Python 3 interpreter found. Please install Python 3 or use the venv.' >&2\n"
|
"echo 'Error: no suitable Python 3 interpreter found. Please install Python 3 or use the venv.' >&2\n"
|
||||||
|
|||||||
@@ -332,8 +332,8 @@ if [[ "$NOINSTALL" != "true" ]]; then # If not explicitly requested, auto-selec
|
|||||||
# Verify the installed CLI module can be imported. This helps catch packaging
|
# Verify the installed CLI module can be imported. This helps catch packaging
|
||||||
# or installation problems early (e.g., missing modules or mispackaged project).
|
# or installation problems early (e.g., missing modules or mispackaged project).
|
||||||
echo "Verifying installed CLI import..."
|
echo "Verifying installed CLI import..."
|
||||||
if "$VENV_PY" -c 'import importlib; importlib.import_module("medeia_macina.cli_entry")' >/dev/null 2>&1; then
|
if "$VENV_PY" -c 'import importlib; importlib.import_module("scripts.cli_entry")' >/dev/null 2>&1; then
|
||||||
echo "OK: 'medeia_macina.cli_entry' is importable in the venv."
|
echo "OK: 'scripts.cli_entry' is importable in the venv."
|
||||||
|
|
||||||
# Ensure the top-level 'CLI' module is importable (required by legacy entrypoints).
|
# Ensure the top-level 'CLI' module is importable (required by legacy entrypoints).
|
||||||
# For PEP 660 editable installs, create a small .pth in the venv site-packages
|
# For PEP 660 editable installs, create a small .pth in the venv site-packages
|
||||||
@@ -372,10 +372,10 @@ PY
|
|||||||
|
|
||||||
# Also verify we can run the packaged entrypoint using module form. If this fails
|
# Also verify we can run the packaged entrypoint using module form. If this fails
|
||||||
# it suggests site-packages/.pth wasn't processed reliably by the interpreter.
|
# it suggests site-packages/.pth wasn't processed reliably by the interpreter.
|
||||||
if "$VENV_PY" -m medeia_macina.cli_entry --help >/dev/null 2>&1; then
|
if "$VENV_PY" -m scripts.cli_entry --help >/dev/null 2>&1; then
|
||||||
echo "OK: 'python -m medeia_macina.cli_entry' runs in the venv." >&2
|
echo "OK: 'python -m scripts.cli_entry' runs in the venv." >&2
|
||||||
else
|
else
|
||||||
echo "ERROR: 'python -m medeia_macina.cli_entry' failed in the venv despite .pth being written; aborting." >&2
|
echo "ERROR: 'python -m scripts.cli_entry' failed in the venv despite .pth being written; aborting." >&2
|
||||||
exit 6
|
exit 6
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
@@ -385,7 +385,7 @@ PY
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
else
|
else
|
||||||
echo "WARNING: Could not import 'medeia_macina.cli_entry' from the venv." >&2
|
echo "WARNING: Could not import 'scripts.cli_entry' from the venv." >&2
|
||||||
echo "Action: Try running: $VENV_PY -m pip install -e \"$REPO/scripts\" or inspect the venv site-packages to verify the installation." >&2
|
echo "Action: Try running: $VENV_PY -m pip install -e \"$REPO/scripts\" or inspect the venv site-packages to verify the installation." >&2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -532,7 +532,7 @@ if [[ "$DESKTOP" == "true" ]]; then
|
|||||||
EXEC_PATH="$VENV_PATH/bin/mm"
|
EXEC_PATH="$VENV_PATH/bin/mm"
|
||||||
if [[ ! -x "$EXEC_PATH" ]]; then
|
if [[ ! -x "$EXEC_PATH" ]]; then
|
||||||
# fallback to python -m
|
# fallback to python -m
|
||||||
EXEC_PATH="$VENV_PY -m medeia_macina.cli_entry"
|
EXEC_PATH="$VENV_PY -m scripts.cli_entry"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
APPDIR="$HOME/.local/share/applications"
|
APPDIR="$HOME/.local/share/applications"
|
||||||
@@ -628,7 +628,7 @@ if [ -n "${MM_DEBUG:-}" ]; then
|
|||||||
import sys, importlib, traceback, importlib.util
|
import sys, importlib, traceback, importlib.util
|
||||||
print('sys.executable:', sys.executable)
|
print('sys.executable:', sys.executable)
|
||||||
print('sys.path (first 8):', sys.path[:8])
|
print('sys.path (first 8):', sys.path[:8])
|
||||||
for mod in ('CLI','medeia_macina','medeia_macina.cli_entry'):
|
for mod in ('CLI','medeia_macina','scripts.cli_entry'):
|
||||||
try:
|
try:
|
||||||
spec = importlib.util.find_spec(mod)
|
spec = importlib.util.find_spec(mod)
|
||||||
print(mod, 'spec:', spec)
|
print(mod, 'spec:', spec)
|
||||||
@@ -646,10 +646,10 @@ fi
|
|||||||
|
|
||||||
# Prefer venv's python3, then venv's python (module invocation - more deterministic)
|
# Prefer venv's python3, then venv's python (module invocation - more deterministic)
|
||||||
if [ -x "$VENV/bin/python3" ]; then
|
if [ -x "$VENV/bin/python3" ]; then
|
||||||
exec "$VENV/bin/python3" -m medeia_macina.cli_entry "$@"
|
exec "$VENV/bin/python3" -m scripts.cli_entry "$@"
|
||||||
fi
|
fi
|
||||||
if [ -x "$VENV/bin/python" ]; then
|
if [ -x "$VENV/bin/python" ]; then
|
||||||
exec "$VENV/bin/python" -m medeia_macina.cli_entry "$@"
|
exec "$VENV/bin/python" -m scripts.cli_entry "$@"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Fallback: packaged console script in the venv (older pip-generated wrapper)
|
# Fallback: packaged console script in the venv (older pip-generated wrapper)
|
||||||
@@ -659,11 +659,11 @@ fi
|
|||||||
|
|
||||||
# Fallback to system python3, then system python (only if it's Python 3)
|
# Fallback to system python3, then system python (only if it's Python 3)
|
||||||
if command -v python3 >/dev/null 2>&1; then
|
if command -v python3 >/dev/null 2>&1; then
|
||||||
exec python3 -m medeia_macina.cli_entry "$@"
|
exec python3 -m scripts.cli_entry "$@"
|
||||||
fi
|
fi
|
||||||
if command -v python >/dev/null 2>&1; then
|
if command -v python >/dev/null 2>&1; then
|
||||||
if python -c 'import sys; sys.exit(0 if sys.version_info[0] >= 3 else 1)'; then
|
if python -c 'import sys; sys.exit(0 if sys.version_info[0] >= 3 else 1)'; then
|
||||||
exec python -m medeia_macina.cli_entry "$@"
|
exec python -m scripts.cli_entry "$@"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -756,7 +756,7 @@ To activate the virtualenv:
|
|||||||
source $VENV_PATH/bin/activate
|
source $VENV_PATH/bin/activate
|
||||||
To run the app:
|
To run the app:
|
||||||
$VENV_PATH/bin/mm # if installed as a console script
|
$VENV_PATH/bin/mm # if installed as a console script
|
||||||
$VENV_PY -m medeia_macina.cli_entry # alternative
|
$VENV_PY -m scripts.cli_entry # alternative
|
||||||
|
|
||||||
Global launcher installed: $USER_BIN/mm
|
Global launcher installed: $USER_BIN/mm
|
||||||
|
|
||||||
|
|||||||
BIN
scripts/cli_entry.py
Normal file
BIN
scripts/cli_entry.py
Normal file
Binary file not shown.
@@ -103,8 +103,8 @@ dev = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
mm = "medeia_macina.cli_entry:main"
|
mm = "scripts.cli_entry:main"
|
||||||
medeia = "medeia_macina.cli_entry:main"
|
medeia = "scripts.cli_entry:main"
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
Homepage = "https://github.com/yourusername/medeia-macina"
|
Homepage = "https://github.com/yourusername/medeia-macina"
|
||||||
|
|||||||
Reference in New Issue
Block a user