Skip to content

Commit

Permalink
Merge branch 'dev' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
cwichel committed Dec 9, 2021
2 parents 7800ef3 + ccd40f4 commit c881dca
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 12 deletions.
2 changes: 1 addition & 1 deletion embutils/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.7.2'
__version__ = '0.7.3'
2 changes: 1 addition & 1 deletion embutils/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@
from .subprocess import execute
from .threading import SDK_TP, AbstractThreadTask, SimpleThreadTask, ThreadPool, get_threads, sync
from .time import Timer, timer
from .venv import activate
from .venv import activate, deactivate
from .version import Version
80 changes: 71 additions & 9 deletions embutils/utils/venv.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#!/usr/bin/python
# -*- coding: ascii -*-
"""
<TBD>
Virtual environment utilities.
:note: Reference implementation.
:date: 2021
:author: Christian Wiche
Expand All @@ -10,7 +12,11 @@
"""

import os
import site
import sys
import typing as tp

import attr

from .common import TPAny
from .path import Path
Expand All @@ -19,6 +25,17 @@


# -->> Definitions <<------------------
@attr.s
class VENV:
"""
Virtual environment info.
"""
os_venv: str = attr.ib(default="")
sys_prefix: str = attr.ib(default=None)


#: History of activated environments
VENVS: tp.List[VENV] = []


# -->> API <<--------------------------
Expand All @@ -35,15 +52,60 @@ def activate(venv: TPAny) -> None:
:raises EnvironmentError: Virtualenv not active or it doesn't match target.
"""
# Path Validation
venv = Path(venv)
script = Path.validate_file(path=venv / "Scripts/activate_this.py", must_exist=True)
venv = Path.validate_dir(path=venv, must_exist=True)
find = list(venv.rglob(pattern="python.exe"))
if not find:
raise EnvironmentError(f"Python interpreter not found on virtual environment: {venv}")

# Activate
old_venv = VENV()

# Get environment paths
bins = venv / "Scripts"
libs = venv / "Libs/site-packages"

# Register environment
if ("VIRTUAL_ENV" in os.environ) and (os.environ["VIRTUAL_ENV"] != ""):
old_venv.os_venv = os.environ["VIRTUAL_ENV"]
os.environ["VIRTUAL_ENV"] = f"{venv}"

# Add binaries to path
os.environ["PATH"] = f"{bins}{os.pathsep}{os.environ['PATH']}"

# Activation
with script.open(mode="r", encoding="utf-8") as file:
code = compile(file.read(), script, "exec")
exec(code, dict(__file__=script))
# Add libraries to host python
idx = len(sys.path)
site.addsitedir(sitedir=libs)
sys.path = sys.path[idx:] + sys.path[0:idx]

# Validation
active = Path(os.environ["VIRTUAL_ENV"]) if ("VIRTUAL_ENV" in os.environ) else sys.executable
# Update system prefix
old_venv.sys_prefix = sys.prefix
sys.prefix = f"{venv}"

# Verify
active = Path(sys.prefix)
if venv != active:
raise EnvironmentError(f"Active environment doesn't match target: {venv} != {active}.")
VENVS.append(old_venv)


def deactivate() -> None:
"""
Deactivates the current virtual environment.
:note: This function can only deactivate environments activated during execution (stored in VENVS).
"""
# Deactivate (only if we activated it)
if VENVS:
old_venv = VENVS.pop(-1)

# Unregister environment
os.environ["VIRTUAL_ENV"] = old_venv.os_venv

# Remove binaries from path
os.environ["PATH"] = f"{os.pathsep}".join(os.environ['PATH'].split(os.pathsep)[1:])

# Remove libraries from host python
sys.path = sys.path[1:]

# Restore system prefix
sys.prefix = old_venv.sys_prefix
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tool.poetry]
version = "0.7.2"
version = "0.7.3"
name = "embutils"
license = "MIT"
readme = "README.md"
Expand Down

0 comments on commit c881dca

Please sign in to comment.