Skip to content

Commit

Permalink
before WSL -> windows transfer
Browse files Browse the repository at this point in the history
  • Loading branch information
cybrdelic committed Oct 11, 2023
1 parent 7c94a3b commit 41efb58
Show file tree
Hide file tree
Showing 11 changed files with 194 additions and 28 deletions.
19 changes: 11 additions & 8 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
name: Python CI
name: Workspace Automator CI/CD

on: [push, pull_request]

jobs:
test:

runs-on: ubuntu-latest
runs-on: windows-latest

steps:
- name: Checkout code
- name: Checkout Code
uses: actions/checkout@v2

- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Install dependencies
python-version: 3.9 # or your preferred version

- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Run tests
pip install pytest
- name: Run Tests
run: |
# Commands to run your tests
pytest tests/
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.venv/
profiles/
__pycache__/
23 changes: 23 additions & 0 deletions Dockerfile.gui
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Use a Windows base image
FROM mcr.microsoft.com/windows/servercore:ltsc2019

# Install Python
ADD https://www.python.org/ftp/python/3.9.7/python-3.9.7-amd64.exe C:\\temp\\python-installer.exe
RUN C:\\temp\\python-installer.exe /quiet InstallAllUsers=1 PrependPath=1 && \
del C:\\temp\\python-installer.exe

# Upgrade pip
RUN python -m pip install --upgrade pip

# Set working directory
WORKDIR /app

# Copy requirements and install
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy the rest of the application
COPY . .

# Command to run your tests (assuming you have a test runner script for Windows)
CMD ["run_tests.bat"]
33 changes: 33 additions & 0 deletions cleanup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/bin/bash

# cleanup.sh

# Directories to clean
DIRS_TO_CLEAN=("build" "codespace_utils.egg-info" "__pycache__" ".pytest_cache")

echo "This script will clean up generated and temporary files."
read -p "Do you want to continue? (y/N): " confirmation

if [[ "$confirmation" != "y" && "$confirmation" != "Y" ]]; then
echo "Cleanup canceled by the user."
exit 1
fi

# Recursively remove __pycache__ from all directories
find . -type d -name "__pycache__" -exec rm -rf {} + \
&& echo "Removed all __pycache__ directories."

# Remove specified directories from the root of the project
for dir in "${DIRS_TO_CLEAN[@]}"; do
if [ -d "$dir" ]; then
rm -rf "$dir"
echo "Removed $dir."
else
echo "$dir does not exist, skipping."
fi
done

# Optionally, you can also remove *.pyc files if they're outside of __pycache__
# find . -type f -name "*.pyc" -delete

echo "Cleanup complete! Remember to regularly commit important changes to version control."
19 changes: 19 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
EasyProcess==1.1
entrypoint2==1.1
iniconfig==2.0.0
jeepney==0.8.0
MouseInfo==0.1.3
mss==9.0.1
packaging==23.2
Pillow==10.0.1
pluggy==1.3.0
PyAutoGUI==0.9.54
PyGetWindow==0.0.9
PyMsgBox==1.0.9
pyperclip==1.8.2
PyRect==0.2.0
pyscreenshot==3.1
PyScreeze==0.1.29
pytest==7.4.2
python3-xlib==0.15
pytweening==1.0.7
3 changes: 3 additions & 0 deletions run_tests.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@echo off
REM Run pytest
python -m pytest
Empty file added tests/__init__.py
Empty file.
28 changes: 28 additions & 0 deletions tests/run_docker_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import os
import subprocess

def build_docker_image():
cmd = [
"docker", "build",
"-t", "gui-tester",
"-f", "Dockerfile.gui",
"."
]
subprocess.run(cmd, check=True)

def run_docker_container():
xauth_path = os.path.expanduser("~/.Xauthority")
cmd = ["docker", "run", "--rm",
"-v", f"{os.getcwd()}/tests/..:/app",
"-v", f"{xauth_path}:/root/.Xauthority",
"-e", "DISPLAY=unix:99",
"gui-tester", "/app/run_tests.sh"]

subprocess.run(cmd, check=True)

def main():
build_docker_image()
run_docker_container()

if __name__ == "__main__":
main()
11 changes: 8 additions & 3 deletions tests/test_process_launcher.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import pytest
from unittest.mock import patch
from utils.process_launcher import ProcessLauncher

def test_process_launcher():
launcher = ProcessLauncher()
# You can mock the subprocess.Popen call or use a dummy safe application to test.
# For now, just a placeholder:
assert launcher

# Mocking the subprocess call
with patch('utils.process_launcher.subprocess.Popen') as mocked_popen:
app = {"path": "dummy_path"}
launcher.launch(app)
mocked_popen.assert_called_once_with(["dummy_path"], shell=True)
41 changes: 37 additions & 4 deletions tests/test_window_manager.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,40 @@
from utils.window_manager import WindowManager
import subprocess
import time
import pytest
from unittest.mock import Mock

def test_window_manager():
@pytest.fixture(autouse=True)
def mock_xlib(monkeypatch):
# Mock the entire Xlib library
mock_xlib = Mock()
monkeypatch.setattr("utils.window_manager.Xlib", mock_xlib)

def test_window_manager_positioning():
manager = WindowManager()
# Testing GUI components like WindowManager can be tricky. Typically, you'd use mock objects or libraries.
# Again, just a placeholder for now:
assert manager

# Launch a dummy X application
subprocess.Popen(["xeyes"])
time.sleep(2) # give some time for the app to launch

app = {
"name": "xeyes",
"position": {
"left": 0,
"top": 0,
"width": "50%",
"height": "100%"
}
}

# Position the window using WindowManager
manager.position_window(app)

# Here comes the tricky part: verifying the window's position and size.
# This would ideally involve querying the X server to get the window's properties
# and check if they match the expected values. Tools like `xwininfo` can be used
# to fetch this info, but parsing and verifying would be non-trivial.

# As a placeholder, let's just check if xeyes is running (this is a very basic check)
result = subprocess.run(["pgrep", "xeyes"], stdout=subprocess.PIPE)
assert result.returncode == 0 # ensures xeyes process was found
44 changes: 31 additions & 13 deletions utils/window_manager.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,53 @@
import pyautogui
import pygetwindow as gw
import time

class WindowManager:
def position_window(self, app):
# Handle monitor selection and switch to the desired monitor
self._switch_monitor(app["monitor"])

# Wait for the application window to appear and get its title
time.sleep(2)
window = self._get_window_by_title(app["name"])

# Handle window positioning
if type(app["position"]) is dict:
self._position_window_by_coordinates(app["position"])
self._position_window_by_coordinates(window, app["position"])
else:
self._position_window_by_keyword(app["position"])
self._position_window_by_keyword(window, app["position"])

# Handle workspace shift if provided
if "workspace" in app:
self._switch_workspace(app["workspace"])

def _switch_monitor(self, monitor_number):
# Logic to switch to the desired monitor (this might require additional logic or libraries)
pass
# For simplicity, we'll just move the mouse to the desired monitor
# You can enhance this logic further
if monitor_number == 1:
pyautogui.moveTo(0, 0)
else:
pyautogui.moveTo(pyautogui.size().width / 2, 0)

def _position_window_by_coordinates(self, position):
# Logic to position window by given coordinates
# This can be based on the previous example using pyautogui
pass
def _position_window_by_coordinates(self, window, position):
# Adjust the window size and position
screen_width, screen_height = pyautogui.size()
width = position["width"] if type(position["width"]) is int else int(screen_width * float(position["width"].strip('%')) / 100)
height = position["height"] if type(position["height"]) is int else int(screen_height * float(position["height"].strip('%')) / 100)
window.resizeTo(width, height)
window.moveTo(position["left"], position["top"])

def _position_window_by_keyword(self, position_keyword):
def _position_window_by_keyword(self, window, position_keyword):
if position_keyword == "maximized":
# Logic to maximize the window (might require additional utilities or libraries)
pass
window.maximize()

def _switch_workspace(self, workspace_number):
# Logic to switch to the desired workspace
pass
# Assuming Ctrl + Win + Left/Right switches workspaces
for _ in range(workspace_number - 1):
pyautogui.hotkey('ctrl', 'win', 'right')

def _get_window_by_title(self, title):
for window in gw.getWindowsWithTitle(''):
if title.lower() in window.title.lower():
return window
return None

0 comments on commit 41efb58

Please sign in to comment.