From 56823a82408f63be849c2fe3cc245079cfcc5ed0 Mon Sep 17 00:00:00 2001 From: David Rubinstein Date: Sat, 1 Apr 2023 01:32:34 -0400 Subject: [PATCH] Add windows support --- .github/workflows/conda.yml | 11 +++++---- .github/workflows/pyenv.yml | 32 ++++++++++++++----------- .github/workflows/venv.yml | 8 +++---- python_compose/unit/conda.py | 24 ++++++++++++------- python_compose/unit/pyenv_virtualenv.py | 31 +++++++++++++++++------- python_compose/unit/venv.py | 22 +++++++++++------ tests/test_compose.py | 6 +++-- 7 files changed, 86 insertions(+), 48 deletions(-) diff --git a/.github/workflows/conda.yml b/.github/workflows/conda.yml index 9d8c363..abe587d 100644 --- a/.github/workflows/conda.yml +++ b/.github/workflows/conda.yml @@ -10,8 +10,10 @@ jobs: matrix: os: - Ubuntu + - Windows + - MacOs py: - - "3.8" + - 3.8 steps: - name: Setup python for test ${{ matrix.py }} @@ -21,11 +23,12 @@ jobs: - uses: conda-incubator/setup-miniconda@v2 with: auto-update-conda: true + auto-activate-base: false python-version: ${{ matrix.python-version}} - uses: actions/checkout@v3 - name: Upgrade pip - run: python -m pip install -U pip + run: python3 -m pip install -U pip - name: Install dependencies - run: python -m pip install -e '.[test]' + run: python3 -m pip install -e '.[test]' - name: Run pytest - run: pytest + run: python3 -m pytest diff --git a/.github/workflows/pyenv.yml b/.github/workflows/pyenv.yml index 5e2ac3e..eb4660f 100644 --- a/.github/workflows/pyenv.yml +++ b/.github/workflows/pyenv.yml @@ -3,23 +3,27 @@ on: [push, pull_request] jobs: job: - name: "Pytest with pyenv" - runs-on: ubuntu-latest + name: test ${{ matrix.py }} - ${{ matrix.os }} + runs-on: ${{ matrix.os }}-latest strategy: matrix: python: - 3.9 + os: + - Ubuntu + - Windows + - MacOs steps: - - uses: actions/checkout@v3 - - name: Install python version - uses: gabrielfalcao/pyenv-action@v13 - with: - default: "${{ matrix.python }}" - command: pip install -U pip # upgrade pip after installing python - - name: Install pyenv-virtualenv - run: git clone https://github.com/pyenv/pyenv-virtualenv.git $(pyenv root)/plugins/pyenv-virtualenv - - name: Install dependencies - run: pip install -e '.[test]' - - name: Run tests - run: pytest + - uses: actions/checkout@v3 + - name: Install python version + uses: gabrielfalcao/pyenv-action@v13 + with: + default: "${{ matrix.python }}" + command: pip3 install -U pip # upgrade pip after installing python + - name: Install pyenv-virtualenv + run: git clone https://github.com/pyenv/pyenv-virtualenv.git $(pyenv root)/plugins/pyenv-virtualenv + - name: Install dependencies + run: pip3 install -e '.[test]' + - name: Run tests + run: python3 -m pytest diff --git a/.github/workflows/venv.yml b/.github/workflows/venv.yml index a53de1c..61c9be8 100644 --- a/.github/workflows/venv.yml +++ b/.github/workflows/venv.yml @@ -10,7 +10,7 @@ jobs: matrix: os: - Ubuntu -# - Windows + - Windows - MacOs py: - "3.11" @@ -25,8 +25,8 @@ jobs: python-version: ${{ matrix.py }} - uses: actions/checkout@v3 - name: Upgrade pip - run: python -m pip install -U pip + run: python3 -m pip install -U pip - name: Install dependencies - run: python -m pip install -e '.[test]' + run: python3 -m pip install -e '.[test]' - name: Run pytest - run: pytest + run: python3 -m pytest diff --git a/python_compose/unit/conda.py b/python_compose/unit/conda.py index 961271e..e457535 100644 --- a/python_compose/unit/conda.py +++ b/python_compose/unit/conda.py @@ -32,13 +32,19 @@ def __init__( def create(self) -> None: """Function for creating a virtual environment.""" - envs = [ - row.split()[0] - for row in subprocess.check_output(["conda", "env", "list"]).decode().split("\n")[2:] - if row - ] + conda_env_list = subprocess.check_output( + ["conda", "env", "list"]).decode().splitlines() + envs = [] + print(conda_env_list) + if len(conda_env_list) >= 2: + envs = [ + row.split()[0] + for row in conda_env_list[2:] + if row + ] if self.name in envs: - warnings.warn(f"Skipping pyenv venv creation for {self.name}. Venv already exists.") + warnings.warn( + f"Skipping pyenv venv creation for {self.name}. Venv already exists.") else: subprocess.check_call(["conda", "create", "-n", self.name, "-y"]) @@ -46,10 +52,12 @@ def install_requirements(self) -> None: """Function to install any and all requirements for running a script in the virtual environment.""" if isinstance(self.requirements, list) and self.requirements: - subprocess.check_call(["conda", "install", "-n", self.name] + self.requirements) + subprocess.check_call( + ["conda", "install", "-n", self.name] + self.requirements) elif isinstance(self.requirements, pathlib.Path): subprocess.check_call( - ["conda", "install", "-n", self.name, "-f", str(self.requirements)] + ["conda", "install", "-n", self.name, + "-f", str(self.requirements)] ) def start(self) -> None: diff --git a/python_compose/unit/pyenv_virtualenv.py b/python_compose/unit/pyenv_virtualenv.py index 66383ad..6656816 100644 --- a/python_compose/unit/pyenv_virtualenv.py +++ b/python_compose/unit/pyenv_virtualenv.py @@ -1,5 +1,6 @@ import os import pathlib +import platform import shutil import subprocess import warnings @@ -37,32 +38,44 @@ def __init__( def create(self) -> None: """Function for creating a virtual environment.""" - self.pyenv_root = pathlib.Path(subprocess.check_output(["pyenv", "root"]).decode().strip()) + self.pyenv_root = pathlib.Path( + subprocess.check_output(["pyenv", "root"]).decode().strip()) self.env_path = self.pyenv_root / "versions" / self.name - self.python_path = self.pyenv_root / "versions" / self.name / "bin" / "python" + if platform.system == "Windows": + self.python_path = self.pyenv_root / "versions" / \ + self.name / "Scripts" / "python.exe" + else: + self.python_path = self.pyenv_root / "versions" / self.name / "bin" / "python" - subprocess.check_call(["pyenv", "install", self.py_version, "--skip-existing"]) + subprocess.check_call( + ["pyenv", "install", self.py_version, "--skip-existing"]) if os.path.exists(self.env_path): - warnings.warn(f"Skipping pyenv venv creation for {self.name}. Venv already exists.") + warnings.warn( + f"Skipping pyenv venv creation for {self.name}. Venv already exists.") else: - subprocess.check_call(["pyenv", "virtualenv", self.py_version, self.name]) + subprocess.check_call( + ["pyenv", "virtualenv", self.py_version, self.name]) def install_requirements(self) -> None: """Function to install any and all requirements for running a script in the virtual environment.""" - subprocess.check_call([str(self.python_path), "-m", "pip", "install", "-U", "pip"]) + subprocess.check_call( + [str(self.python_path), "-m", "pip", "install", "-U", "pip"]) if isinstance(self.requirements, list) and self.requirements: subprocess.check_call( - [str(self.python_path), "-m", "pip", "install"] + self.requirements + [str(self.python_path), "-m", "pip", + "install"] + self.requirements ) elif isinstance(self.requirements, pathlib.Path): subprocess.check_call( - [str(self.python_path), "-m", "pip", "install", "-r", str(self.requirements)] + [str(self.python_path), "-m", "pip", + "install", "-r", str(self.requirements)] ) def start(self) -> None: """Function to start a script in the previously created virtual environment""" - p = subprocess.Popen([str(self.python_path), str(self.script_path)] + self.script_args) + p = subprocess.Popen([str(self.python_path), str( + self.script_path)] + self.script_args) p.communicate() def clean(self) -> None: diff --git a/python_compose/unit/venv.py b/python_compose/unit/venv.py index 7411cb2..1a67e44 100644 --- a/python_compose/unit/venv.py +++ b/python_compose/unit/venv.py @@ -1,8 +1,10 @@ +import os import pathlib +import platform import shutil import subprocess +import venv from typing import List, Union -from venv import EnvBuilder from python_compose.unit.compose_unit import ComposeUnit @@ -31,31 +33,37 @@ def __init__( self.name = name self.env_dir = env_dir self.env_path = self.env_dir / self.name - self.python_path = self.env_path / "bin" / "python" + if platform.system() == "Windows": + self.python_path = self.env_path / "Scripts" / "python.exe" + else: + self.python_path = self.env_path / "bin" / "python" self.requirements = requirements self.script_path = script_path self.script_args = script_args def create(self) -> None: """Function for creating a virtual environment.""" - self.env = EnvBuilder(system_site_packages=True, clear=False, with_pip=True) - self.env.create(self.env_path) + venv.create(str(self.env_path), system_site_packages=True, + clear=False, with_pip=True) def install_requirements(self) -> None: """Function to install any and all requirements for running a script in the virtual environment.""" if isinstance(self.requirements, list) and self.requirements: subprocess.check_call( - [str(self.python_path), "-m", "pip", "install"] + self.requirements + [str(self.python_path), "-m", "pip", + "install"] + self.requirements ) elif isinstance(self.requirements, pathlib.Path): subprocess.check_call( - [str(self.python_path), "-m", "pip", "install", "-r", str(self.requirements)] + [str(self.python_path), "-m", "pip", + "install", "-r", str(self.requirements)] ) def start(self) -> None: """Function to start a script in the previously created virtual environment.""" - p = subprocess.Popen([str(self.python_path), str(self.script_path)] + self.script_args) + p = subprocess.Popen([str(self.python_path), str( + self.script_path)] + self.script_args) p.communicate() def clean(self) -> None: diff --git a/tests/test_compose.py b/tests/test_compose.py index 7a1e8e2..e7a5bc0 100644 --- a/tests/test_compose.py +++ b/tests/test_compose.py @@ -1,5 +1,6 @@ import os import pathlib +import platform import random import shutil import string @@ -62,7 +63,7 @@ def test_conda(tmp_path: pathlib.Path, random_string: str) -> None: "test", [], [ - "python", + "python3", os.path.join("tests", "create_file.py"), str(output_file), random_string, @@ -84,7 +85,8 @@ def test_yaml_deserialization() -> None: def test_pydantic_to_compose_unit() -> None: - units = compose.pydantic_to_units(compose.from_yaml(pathlib.Path("tests") / "config.yaml")) + units = compose.pydantic_to_units( + compose.from_yaml(pathlib.Path("tests") / "config.yaml")) assert len(units) == 3 counter: Counter[str] = Counter() for unit in units: