2025-07-29 11:31:49 +02:00

182 lines
4.9 KiB
Python

import sys
from pathlib import Path
import stat
import subprocess
import logging
import toml
from . import get_response
from .static import Situation
from .config import CONFIG_FILES, CONFIG_DIRECTORY, generate_current_configuration
logging.basicConfig(
format=' %(message)s',
force=True,
)
log_level = logging.INFO
mommy_logger = logging.getLogger("mommy")
mommy_logger.setLevel(logging.INFO)
serious_logger = logging.getLogger("serious")
serious_logger.setLevel(logging.WARNING)
def development():
s = "positive"
if len(sys.argv) > 1:
s = sys.argv[1]
print(get_response(Situation(s)))
def write_current_config():
f = "python-mommy.toml"
if len(sys.argv) > 1:
f = sys.argv[1]
config_file = CONFIG_DIRECTORY / f
print(f"writing to: {config_file}")
data = toml.dumps(generate_current_configuration())
print(data)
with config_file.open("w") as f:
f.write(data)
WRAPPER_TEMPLATE = """#!{inner_bin}
# -*- coding: utf-8 -*-
import sys, subprocess
from python_mommy_venv import get_response, Situation
INTERPRETER = "{inner_bin}"
result = subprocess.run([INTERPRETER] + sys.argv[1:])
code = result.returncode
print()
print(get_response(Situation.POSITIVE if code == 0 else Situation.NEGATIVE))
exit(code=code)
"""
PIP_HOOK = """# GENERATED BY MOMMY
code = main()
from pathlib import Path
bin_path = Path(".venv", "bin")
python_interpreter_wrappers = []
for path in bin_path.iterdir():
if path.is_symlink() and path.name.startswith("inner_"):
python_interpreter_wrappers.append(path.name.replace("inner_", "", 1))
for path in bin_path.iterdir():
if path.is_symlink():
continue
if path.name in python_interpreter_wrappers:
continue
text: str
with path.open("r") as f:
text = f.read()
first_line = text.split("\\n")[0]
if not ("inner_" in first_line and first_line.startswith("#!")):
continue
print(f"mommifying " + str(path))
text = text.replace("inner_", "", 1)
with path.open("w") as f:
f.write(text)
sys.exit(code)"""
def wrap_interpreter(path: Path):
mommy_logger.info("mommy found a symlink to an interpreter~ %s", str(path))
serious_logger.info("interpreter symlink found at %s", str(path))
inner_symlink = path.parent / ("inner_" + path.name)
symlink_target = path.resolve()
if inner_symlink.exists():
raise Exception("inner symlink somehow already exists. This shouldn't happen because of prior checks")
mommy_logger.info("mommy shows her girl where the interpreter is: %s -> %s", inner_symlink, symlink_target)
serious_logger.info("creating symlink: %s -> %s", inner_symlink, symlink_target)
inner_symlink.symlink_to(symlink_target)
# remove original symlink
mommy_logger.info("mommy deletes the original interpreter~ %s", path)
serious_logger.info("deleting original symlink %s", path)
path.unlink()
# creating the wrapper string
mommy_logger.info("mommy writes wrapper script as %s", Path)
serious_logger.info("writing wrapper script at %s", path)
with path.open("w") as f:
f.write(WRAPPER_TEMPLATE.format(inner_bin=str(inner_symlink)))
serious_logger.info("making wrapper script executable")
path.chmod(path.stat().st_mode | stat.S_IEXEC)
def install_pip_hook(path: Path):
text: str
with path.open("r") as f:
text = f.read()
if "# GENERATED BY MOMMY" in text:
mommy_logger.info("ahhhhh mommy already watches %s", str(path))
serious_logger.info("pip hook already installed at %s", str(path))
return
mommy_logger.info("mommy needs to keep an eye on this little pip~ %s", str(path))
serious_logger.info("installing pip hook at %s", str(path))
text = text.replace("sys.exit(main())", PIP_HOOK, 1)
with path.open("w") as f:
f.write(text)
def mommify_venv():
v = ".venv"
if len(sys.argv) > 1:
v = sys.argv[1]
bin_path = Path(v, "bin")
bin_path = bin_path.resolve()
mommy_logger.info("mommy looks in %s to mess your system up~ <33", str(bin_path))
serious_logger.info("scanning binary directory of venv at %s", str(bin_path))
for path in list(bin_path.iterdir()):
name = path.name
if path.is_symlink():
# could be python interpreter
# check for both just to be more expressive
if name.startswith("inner_") or not name.startswith("python"):
continue
if subprocess.run([str(path), '-c', '"exit()"']) != 0:
continue
wrap_interpreter(path)
else:
# could be pip
if not name.startswith("pip"):
continue
install_pip_hook(path)
serious_logger.info("")
mommy_logger.info("")