Metadata-Version: 2.4
Name: gpscheduler
Version: 0.1.0
Summary: A cron-style scheduler that turns functions from any package into scheduled jobs via config files.
Project-URL: Homepage, https://github.com/LinnetCodes/gpscheduler
Project-URL: Documentation, https://linnetcodes.github.io/gpscheduler/
Project-URL: Repository, https://github.com/LinnetCodes/gpscheduler
Project-URL: Issues, https://github.com/LinnetCodes/gpscheduler/issues
Project-URL: Changelog, https://github.com/LinnetCodes/gpscheduler/releases
Project-URL: PyPI, https://pypi.org/project/gpscheduler/
Author-email: Linnet Codes <linnet.codes@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: automation,cron,scheduler,scheduling,task-scheduler
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: apscheduler<4,>=3.10
Requires-Dist: click>=8.0.0
Requires-Dist: gpclog>=0.3.0
Requires-Dist: gpconfig>=0.3.0
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest-cov>=5; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Requires-Dist: twine>=5; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
Requires-Dist: mkdocs-static-i18n>=1.2; extra == 'docs'
Requires-Dist: mkdocs>=1.6; extra == 'docs'
Requires-Dist: mkdocstrings[python]>=0.25; extra == 'docs'
Description-Content-Type: text/markdown

# gpscheduler

[![PyPI version](https://img.shields.io/pypi/v/gpscheduler.svg)](https://pypi.org/project/gpscheduler/)
[![Python](https://img.shields.io/pypi/pyversions/gpscheduler.svg)](https://pypi.org/project/gpscheduler/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Documentation](https://img.shields.io/badge/docs-mkdocs-blue.svg)](https://linnetcodes.github.io/gpscheduler/)

**GPScheduler** (General-Purpose Scheduler) is a cron-style Python scheduler that turns
functions from any package into scheduled jobs via config files, configures startup
arguments, and exposes a decorator to mark schedulable functions.

> **中文文档**：[README.zh.md](README.zh.md)

---

## Features

- **Config-driven cron jobs** — declare schedules, callables, and call arguments in YAML
  config files; no timers hardcoded in application code.
- **Package-agnostic** — point a job at any importable function in any installed package,
  located by dotted path.
- **Two decorators** — `@scheduled` marks a function as schedulable; `@worker_init` builds
  an expensive object (DB connection, network client, …) once and reuses it across runs.
- **Thread and process executors** — each job picks its own pool. Threads for I/O-bound
  work, processes for CPU-bound or isolated work.
- **Scheduler-wide globals** — shared config values (`db_url`, `api_key`, …) injected into
  every job that asks for them.
- **Graceful, cross-platform shutdown** — `Ctrl+C` on Windows, `SIGINT`/`SIGTERM` on
  Linux, with a configurable shutdown timeout.
- **Fail-Early validation** — invalid config fails loudly at load time, never silently at
  the first trigger.
- **Embeddable** — run standalone via the CLI, or embed it inside a host application.

## Installation

```bash
pip install gpscheduler
```

For local development from a clone:

```bash
source .venv/Scripts/activate   # Git Bash on Windows
pip install -e ".[dev]"
```

## Quick start

1. Install gpscheduler (see [Installation](#installation)).

2. Write a package containing a `@scheduled` function:

   ```python
   # myjobs/hello.py
   from gpscheduler import scheduled

   @scheduled
   def greet(name: str, *, greeting: str = "Hello") -> None:
       print(f"{greeting}, {name}!")
   ```

3. Point a config folder at it:

   ```yaml
   # configs/scheduler.yaml
   cfg_class_name: GPSchedulerConfig
   configured_class_name: GPScheduler
   executor: thread
   packages: [myjobs]
   ```

   ```yaml
   # configs/jobs/hello.yaml
   cfg_class_name: GPJobConfig
   func: "myjobs.hello.greet"
   cron: "*/2 * * * * *"   # every 2 seconds (6-segment, leading seconds field)
   args: ["world"]
   kwargs:
     greeting: "Hi"
   ```

   The config folder also needs a `global_env.yaml` (required by the underlying
   [gpconfig](https://github.com/LinnetCodes/gpconfig) loader) — an empty `{}` is fine.

4. Run it:

   ```bash
   gpscheduler run --config configs
   ```

   Use `gpscheduler list-jobs --config configs` for a dry run that validates config and
   lists enabled jobs without starting anything.

See the [Examples](https://linnetcodes.github.io/gpscheduler/examples/) page in the docs
for a complete, annotated demo covering arguments, `job_globals` injection, `worker_init`
in both thread and process pools, and more.

## Documentation

Full documentation is published at <https://linnetcodes.github.io/gpscheduler/>
(English / 简体中文).

## License

[MIT](LICENSE) © LinnetCodes
