Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 0 additions & 51 deletions .github/workflows/build.yaml

This file was deleted.

151 changes: 151 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
name: Check and Build

on:
push:
branches:
- main
pull_request:
workflow_dispatch:
release:
types:
- released
Comment thread
coderabbitai[bot] marked this conversation as resolved.

permissions: read-all

jobs:
lint:
name: Lint codebase
runs-on: ubuntu-latest
strategy:
matrix:
python: &python-versions
- "3.11"
- "3.12"
- "3.13"
- "3.14"
steps:
- name: Checkout the Git repository
uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python }}
cache: pip
- &install-emake
name: Install emake
run: pip install emake
- name: Run lint
run: emake lint
Comment thread
Eeems marked this conversation as resolved.

build-sdist:
name: Build sdist
needs: &build-needs
- lint
runs-on: ubuntu-latest
steps:
- name: Checkout the Git repository
uses: actions/checkout@v6
- *install-emake
- name: Building sdist
run: emake build --sdist
- uses: actions/upload-artifact@v6
with:
name: pip-sdist
path: dist/*
if-no-files-found: error

build-any-wheel:
name: Build wheel
Comment thread
Eeems marked this conversation as resolved.
needs: *build-needs
runs-on: ubuntu-latest
steps:
- name: Checkout the Git repository
uses: actions/checkout@v6
- *install-emake
- name: Building wheel
run: emake build --wheel
- uses: actions/upload-artifact@v6
with:
name: pip-wheel-none-any
path: dist/*
if-no-files-found: error

build-wheel:
name: Build wheel
needs: *build-needs
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python: *python-versions
arch:
- aarch64
- armv7l
libc:
- glibc
steps:
- name: Checkout the Git repository
uses: actions/checkout@v6
- *install-emake
- name: Building wheel
run: |
emake build \
--native-wheel \
--arch ${{ matrix.arch }} \
--libc ${{ matrix.libc }} \
--python ${{ matrix.python }}
Comment thread
Eeems marked this conversation as resolved.
- uses: actions/upload-artifact@v6
with:
name: pip-wheel-${{ matrix.python }}-${{ matrix.arch }}-${{ matrix.libc }}
path: dist/*
if-no-files-found: error

publish:
name: Publish to PyPi
if: github.event_name == 'release' && startsWith(github.ref, 'refs/tags')
needs: &release-needs
- build-sdist
- build-any-wheel
- build-wheel
runs-on: ubuntu-latest
permissions:
id-token: write
environment:
name: pypi
url: https://pypi.org/p/launcherctl
steps:
- name: Download pip packages
id: download
uses: actions/download-artifact@v8
with:
pattern: pip-*
merge-multiple: true
path: dist
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: ${{ steps.download.outputs.download-path }}
skip-existing: true
Comment thread
coderabbitai[bot] marked this conversation as resolved.

release:
name: Add release artifacts
if: github.event_name == 'release' && startsWith(github.ref, 'refs/tags')
needs: *release-needs
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout the Git repository
uses: actions/checkout@v6
- name: Download artifact
id: download
uses: actions/download-artifact@v8
with:
pattern: pip-*
merge-multiple: true
path: dist
- name: Upload to release
run: find . -type f | xargs -rI {} gh release upload "$TAG" {} --clobber
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ github.event.release.tag_name }}
working-directory: ${{ steps.download.outputs.download-path }}
Comment thread
Eeems marked this conversation as resolved.
34 changes: 2 additions & 32 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,8 @@ pip install --force-reinstall /tmp/launcherctl-${VERSION}-py3-none-any.whl
endef
export SCRIPT

ifeq ($(VENV_BIN_ACTIVATE),)
VENV_BIN_ACTIVATE := .venv/bin/activate
endif


dist/launcherctl-${VERSION}.tar.gz: $(shell find launcherctl -type f)
python -m build --sdist

dist/launcherctl-${VERSION}-py3-none-any.whl: $(shell find launcherctl -type f)
python -m build --wheel
emake build --wheel

clean:
git clean --force -dX
Expand All @@ -40,26 +32,4 @@ test: install
| ssh root@10.11.99.1 \
"bash -ec 'PATH=${PATH} /opt/bin/python -u'"

$(VENV_BIN_ACTIVATE):
@echo "Setting up development virtual env in .venv"
python -m venv .venv
. $(VENV_BIN_ACTIVATE); \
python -m pip install ruff

lint: $(VENV_BIN_ACTIVATE)
. $(VENV_BIN_ACTIVATE); \
python -m ruff check

lint-fix: $(VENV_BIN_ACTIVATE)
. $(VENV_BIN_ACTIVATE); \
python -m ruff check

format: $(VENV_BIN_ACTIVATE)
. $(VENV_BIN_ACTIVATE); \
python -m ruff format --diff

format-fix: $(VENV_BIN_ACTIVATE)
. $(VENV_BIN_ACTIVATE); \
python -m ruff format

.PHONY: clean install test deploy lint lint-fix format format-fix
.PHONY: clean install test deploy
32 changes: 11 additions & 21 deletions launcherctl/_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@


class App:
def __init__(self, name: str):
self.name = name
def __init__(self, name: str) -> None:
self.name: str = name

@property
def is_running(self) -> bool:
Expand All @@ -14,21 +14,21 @@ def is_paused(self) -> bool:
return self.name in api.paused.keys()

def start(self) -> None:
launcherctl("start-app", self.name)
_ = launcherctl("start-app", self.name)

def stop(self) -> None:
launcherctl("stop-app", self.name)
_ = launcherctl("stop-app", self.name)

def pause(self) -> None:
launcherctl("pause-app", self.name)
_ = launcherctl("pause-app", self.name)

def resume(self) -> None:
launcherctl("resume-app", self.name)
_ = launcherctl("resume-app", self.name)


class API:
def keys(self) -> list[str]:
return [x.decode("utf-8") for x in launcherctl("list-apps").splitlines()]
return launcherctl("list-apps").splitlines()

def __contains__(self, key: str) -> bool:
return key in self.keys()
Expand All @@ -40,22 +40,12 @@ def __getitem__(self, key: str) -> App:
return App(key)

@property
def running(self) -> dict[App]:
return {
x: App(x)
for x in [
x.decode("utf-8") for x in launcherctl("list-running-apps").splitlines()
]
}
def running(self) -> dict[str, App]:
return {x: App(x) for x in launcherctl("list-running-apps").splitlines()}

@property
def paused(self) -> dict[App]:
return {
x: App(x)
for x in [
x.decode("utf-8") for x in launcherctl("list-paused-apps").splitlines()
]
}
def paused(self) -> dict[str, App]:
return {x: App(x) for x in launcherctl("list-paused-apps").splitlines()}


api = API()
38 changes: 18 additions & 20 deletions launcherctl/_launcher.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,28 @@
import subprocess
from collections.abc import Callable

from typing import Callable

from ._app import App
from ._util import launcherctl


class Launcher:
def __init__(self, name: str):
self.name = name
def __init__(self, name: str) -> None:
self.name: str = name

def logs(self, onlogline: Callable[[str], None] = None) -> list[str] | None:
pass
def logs(self, _onlogline: Callable[[str], None] | None = None) -> list[str] | None:
raise NotImplementedError()

def start(self):
launcherctl("start-launcher", self.name)
def start(self) -> None:
_ = launcherctl("start-launcher", self.name)

def stop(self):
launcherctl("stop-launcher", self.name)
def stop(self) -> None:
_ = launcherctl("stop-launcher", self.name)

def enable(self, start: bool = False):
def enable(self, start: bool = False) -> None:
if start:
launcherctl("switch-launcher", "--start", self.name)
_ = launcherctl("switch-launcher", "--start", self.name)

else:
launcherctl("switch-launcher", self.name)
_ = launcherctl("switch-launcher", self.name)

@property
def is_current(self) -> bool:
Expand All @@ -50,23 +48,23 @@ def is_active(self) -> bool:

class API:
def keys(self) -> list[str]:
return [x.decode("utf-8") for x in launcherctl("list-launchers").splitlines()]
return launcherctl("list-launchers").splitlines()

def __contains__(self, key: str) -> bool:
return key in self.keys()

def __getitem__(self, key: str) -> App:
def __getitem__(self, key: str) -> Launcher:
if key not in self:
raise KeyError()

return Launcher(key)

@property
def current(self):
return Launcher(launcherctl("status").splitlines()[0][14:-4].decode("utf-8"))
def current(self) -> Launcher:
return Launcher(launcherctl("status").splitlines()[0][14:-4])
Comment thread
Eeems marked this conversation as resolved.

def switch(launcher: Launcher | str, start: bool = False):
if not isinstance(Launcher, launcher):
def switch(self, launcher: Launcher | str, start: bool = False) -> None:
if not isinstance(launcher, Launcher):
launcher = Launcher(launcher)

launcher.enable(start)
Expand Down
Loading
Loading