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: 24 additions & 27 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,19 @@ jobs:
# continue-on-error: ${{ matrix.platform == 'windows-latest' }}

steps:
# ugh https://github.com/actions/toolkit/blob/main/docs/commands.md#path-manipulation
- run: echo "$HOME/.local/bin" >> $GITHUB_PATH

- uses: actions/checkout@v6
with:
submodules: recursive
fetch-depth: 0 # nicer to have all git history when debugging/for tests

- uses: actions/setup-python@v6
- uses: astral-sh/setup-uv@v8.1.0
with:
python-version: ${{ matrix.python-version }}

- uses: astral-sh/setup-uv@v7
with:
enable-cache: false # we don't have lock files, so can't use them as cache key
enable-cache: false # we don't have lock files during initial CI checkout, so can't use them as cache key

- uses: mxschmitt/action-tmate@v3
with:
limit-access-to-actor: true # restrict to the user who kicked off pipeline
if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}

# explicit bash command is necessary for Windows CI runner, otherwise it thinks it's cmd...
Expand All @@ -66,7 +62,7 @@ jobs:
CI_MYPY_COVERAGE: ${{ matrix.platform == 'ubuntu-latest' && '--cobertura-xml-report .coverage.mypy' || '' }}

- if: matrix.platform == 'ubuntu-latest' # no need to compute coverage for other platforms
uses: codecov/codecov-action@v5
uses: codecov/codecov-action@v6
with:
fail_ci_if_error: true # default false
token: ${{ secrets.CODECOV_TOKEN }}
Expand All @@ -77,7 +73,7 @@ jobs:
pypi:
# Do not run it for PRs/cron schedule etc.
# NOTE: release tags are guarded by on: push: tags on the top.
if: github.event_name == 'push' && (startsWith(github.event.ref, 'refs/tags/') || (github.event.ref == format('refs/heads/{0}', github.event.repository.master_branch)))
if: github.event_name == 'push' && (github.ref_type == 'tag' || github.ref_name == github.event.repository.master_branch)
# Ugh, I tried using matrix or something to explicitly generate only test pypi or prod pypi pipelines.
# But github actions is so shit, it's impossible to do any logic at all, e.g. doesn't support conditional matrix, if/else statements for variables etc.

Expand All @@ -88,30 +84,31 @@ jobs:
permissions:
# necessary for Trusted Publishing
id-token: write

env:
# always deploy merged master to test pypi
# always deploy tags to release pypi
TARGET: ${{ github.ref_type == 'tag' && 'pypi' || 'testpypi' }}
environment:
# for "deployments" tab on github
# sadly can't reuse env.TARGET here...
name: ${{ github.ref_type == 'tag' && 'pypi' || 'testpypi' }}
url: https://${{ github.ref_type == 'tag' && 'pypi.org' || 'test.pypi.org' }}/project/${{ steps.meta.outputs.pypi_name }}/
steps:
# ugh https://github.com/actions/toolkit/blob/main/docs/commands.md#path-manipulation
- run: echo "$HOME/.local/bin" >> $GITHUB_PATH

- uses: actions/checkout@v6
with:
submodules: recursive
fetch-depth: 0 # pull all commits to correctly infer vcs version

- uses: actions/setup-python@v6
- uses: astral-sh/setup-uv@v8.1.0
with:
python-version: '3.12'
enable-cache: false # we don't have lock files during initial CI checkout, so can't use them as cache key

- uses: astral-sh/setup-uv@v7
with:
enable-cache: false # we don't have lock files, so can't use them as cache key
- name: 'release ${{ steps.meta.outputs.pypi_name }} to ${{ env.TARGET }}'
run: .ci/release ${{ env.TARGET == 'testpypi' && '--use-test-pypi' || '' }}

- name: 'release to test pypi'
# always deploy merged master to test pypi
if: github.event.ref == format('refs/heads/{0}', github.event.repository.master_branch)
run: .ci/release --use-test-pypi

- name: 'release to prod pypi'
# always deploy tags to release pypi
if: startsWith(github.event.ref, 'refs/tags/')
run: .ci/release
- id: meta
shell: bash
run: |
pypi_name=$(unzip -p dist/*.whl '*.dist-info/METADATA' | awk '/^Name:/ {print $2; exit}')
echo "pypi_name=$pypi_name" >> "$GITHUB_OUTPUT"
File renamed without changes.
8 changes: 4 additions & 4 deletions mypy.ini
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
[mypy]
pretty = True
show_error_context = True
show_column_numbers = True
show_error_end = True

check_untyped_defs = True

# see https://mypy.readthedocs.io/en/stable/error_code_list2.html
## NOTE: strict implies all of these.. will gradually move onto it
strict = False
check_untyped_defs = True
warn_redundant_casts = True
strict_equality = True
warn_unused_ignores = True
##
enable_error_code = deprecated,redundant-expr,possibly-undefined,truthy-bool,truthy-iterable,ignore-without-code,unused-awaitable


# an example of suppressing
# [mypy-my.config.repos.pdfannots.pdfannots]
# ignore_errors = True
28 changes: 13 additions & 15 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,14 @@ dependencies = [
"dbus-python; platform_system != 'Darwin'", # dbus interface to systemd
]
requires-python = ">=3.12"
# FIXME dbus

## these need to be set if you're planning to upload to pypi
## these are only useful for pypi
description = "What if cron and systemd had a baby?"
license = {file = "LICENSE.txt"}
authors = [
{name = "Dima Gerasimov (@karlicoss)", email = "karlicoss@gmail.com"},
]
maintainers = [
{name = "Dima Gerasimov (@karlicoss)", email = "karlicoss@gmail.com"},
]
[project.urls]
license = {file = "LICENSE"}
authors = [{name = "Dima Gerasimov (@karlicoss)", email = "karlicoss@gmail.com"}]
maintainers = [{name = "Dima Gerasimov (@karlicoss)", email = "karlicoss@gmail.com"}]

[project.urls] # pypi will fetch some github stats/link, so somewhat useful
Homepage = "https://github.com/karlicoss/dron"
##

Expand All @@ -36,6 +32,7 @@ notify-telegram = [
# see https://github.com/rahiel/telegram-send/issues/115#issuecomment-1368728425
"telegram-send>=0.37",
]

[dependency-groups]
testing = [
"pytest>=9", # need version 9 for proper namespace package support
Expand All @@ -44,16 +41,14 @@ testing = [
"dron[notify-telegram]",
]
typecheck = [
{ include-group = "testing" },
"mypy",
"lxml", # for mypy html coverage
"ty>=0.0.3",
"ty>=0.0.38",

"types-tabulate",
]

[project.scripts]
dron = "dron.__main__:main"
{ include-group = "testing" },
]


[build-system]
Expand All @@ -70,3 +65,6 @@ source = "vcs"
[tool.hatch.version.raw-options]
version_scheme = "python-simplified-semver"
local_scheme = "dirty-tag"

[project.scripts]
dron = "dron.__main__:main"
12 changes: 12 additions & 0 deletions ruff.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ lint.extend-select = [
]

lint.ignore = [
"CPY", # copyright headers
"D", # annoying nags about docstrings
"N", # pep naming
"TCH", # type checking rules, mostly just suggests moving imports under TYPE_CHECKING
Expand All @@ -16,6 +17,9 @@ lint.ignore = [
"EM" , # suggests assigning all exception messages into a variable first... pretty annoying

### too opinionated style checks
"E203", # whitespace before , -- sometimes used for readability, and ruff format should cover it anyway
"E221", # multiple spaces before operator -- also covered by ruff format
"E266", # too many leading '#' for block comment -- sometimes genuinely useful for visual separation
"E501", # too long lines
"E731", # assigning lambda instead of using def
"E741", # Ambiguous variable name: `l`
Expand Down Expand Up @@ -63,6 +67,8 @@ lint.ignore = [
"RET504", # unnecessary assignment before returning -- that can be useful for readability
"RET505", # unnecessary else after return -- can hurt readability

"PLC1901", # suggests using `if string` instead of `strinig == ""` -- dumb.

"PLW0603", # global variable update.. we usually know why we are doing this
"PLW2901", # for loop variable overwritten, usually this is intentional

Expand Down Expand Up @@ -96,4 +102,10 @@ lint.ignore = [
##

"PLC0415", # "imports should be at the top level" -- not realistic

"RUF067", # `__init__` module should only contain docstrings and re-exports -- might be nice to aim for, but dunno
]


extend-exclude = [
]
2 changes: 1 addition & 1 deletion src/dron/launchd.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def plist(
# maybe we just want bash -c in this case, dunno how to implement properly
raise RuntimeError(command) # too ambiguous?
else: # must be an actual sequence of path-like things
cmd = tuple(map(str, command)) # ty: ignore[invalid-argument-type] # see https://github.com/astral-sh/ty/issues/2087
cmd = tuple(map(str, command))
del command

mschedule = ''
Expand Down
3 changes: 1 addition & 2 deletions src/dron/launchd_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@
PYCACHE_PATH = Path('~/.cache/pycache').expanduser()


# ty doesn't support NoReturn yet, see https://github.com/astral-sh/ty/issues/180
def main() -> NoReturn: # ty: ignore[invalid-return-type]
def main() -> NoReturn:
p = argparse.ArgumentParser()
p.add_argument('--notify', action='append')
p.add_argument('--job', required=True)
Expand Down
3 changes: 1 addition & 2 deletions src/dron/notify/ntfy_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@
from typing import NoReturn


# ty doesn't support NoReturn yet, see https://github.com/astral-sh/ty/issues/180
def run_ntfy(*, job: str, backend: str) -> NoReturn: # ty: ignore[invalid-return-type]
def run_ntfy(*, job: str, backend: str) -> NoReturn:
# TODO not sure what to do with --stdin arg here?
# could probably use last N lines of log or something
# TODO get last logs here?
Expand Down
4 changes: 2 additions & 2 deletions src/dron/systemd.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ def _sd(s: str) -> str:
class BusManager:
def __init__(self) -> None:
# unused-ignore because on macos there is no dbus (but this code is still running mypy on CI)
from dbus import ( # type: ignore[import-untyped,import-not-found,unused-ignore]
from dbus import ( # type: ignore[import-untyped,import-not-found,unused-ignore] # ty: ignore[unresolved-import]
Interface,
SessionBus,
)
Expand Down Expand Up @@ -309,7 +309,7 @@ def test_managed_units() -> None:
# dbus.exceptions.DBusException: org.freedesktop.DBus.Error.BadAddress: Address does not contain a colon
# todo maybe don't need it anymore with 20.04 circleci?
if 'CI' not in os.environ:
cmd_monitor.callback(n=1, once=True, command=True, rate=True) # type: ignore[misc]
cmd_monitor.callback(n=1, once=True, command=True, rate=True) # type: ignore[misc] # ty: ignore[call-non-callable]


def skip_if_no_systemd() -> None:
Expand Down