Metadata-Version: 2.4
Name: crontable
Version: 0.2.0
Summary: A generic mini scheduler supporting CSV date-based and crontab-style tasks
Project-URL: Homepage, https://github.com/erim32/crontable
Project-URL: Issues, https://github.com/erim32/crontable/issues
Author-email: Remi <contact@erim.fr>
License: PolyForm Noncommercial License 1.0.0
        
        Copyright (c) 2026 Remi <contact@erim.fr>
        
        Acceptance
        
        In order to get any license under these terms, you must agree
        to them as both strict obligations and conditions to all
        your licenses.
        
        Copyright License
        
        The licensor grants you a copyright license for the
        software to do everything you might do with the software
        that would otherwise infringe the licensor's copyright
        in it for any permitted purpose. However, you may
        only distribute the software according to Distribution
        License and make changes or new works based on the
        software according to Changes and New Works License.
        
        Distribution License
        
        The licensor grants you an additional copyright license
        to distribute copies of the software. Your license
        to distribute covers distributing the software with
        changes and new works permitted by Changes and New
        Works License.
        
        Notices
        
        You must ensure that anyone who gets a copy of
        any part of the software from you also gets a copy
        of these terms or the URL for them above, as well
        as copies of any plain-text lines beginning with
        Required Notice: that the licensor provided with
        the software. For example:
        
            Required Notice: Copyright Remi (https://github.com/erim32/crontable)
        
        Changes and New Works License
        
        The licensor grants you an additional copyright license
        to make changes and new works based on the software
        for any permitted purpose.
        
        Patent License
        
        The licensor grants you a patent license for the
        software that covers patent claims the licensor can
        license, or becomes able to license, that you would
        infringe by using the software.
        
        Noncommercial Purposes
        
        Any noncommercial purpose is a permitted purpose.
        
        Personal Uses
        
        Personal use for research, experiment, and testing for
        the benefit of public knowledge, personal study,
        private entertainment, hobby projects, amateur pursuits,
        or religious observance, without any anticipated
        commercial application, is use for a permitted purpose.
        
        Noncommercial Organizations
        
        Use by any charitable organization, educational institution,
        public research organization, public safety or health
        organization, environmental protection organization,
        or government institution is use for a permitted purpose
        regardless of the source of funding or obligations
        resulting from the funding.
        
        Fair Use
        
        You may have "fair use" rights for the software under
        the law. These terms do not limit them.
        
        No Other Rights
        
        These terms do not allow you to sublicense or transfer
        any of your licenses to anyone else, or prevent the
        licensor from granting licenses to anyone else. These
        terms do not imply any other licenses.
        
        Patent Defense
        
        If you make any written claim that the software infringes
        or contributes to infringement of any patent, your patent
        license for the software granted under these terms ends
        immediately. If your employer makes such a claim, your
        patent license ends immediately for work on behalf of
        your employer.
        
        Violations
        
        The first time you are notified in writing that you have
        violated any of these terms, or done anything with the
        software not covered by your licenses, your licenses can
        nonetheless continue if you come into full compliance
        with these terms, and take practical steps to correct
        past violations, within 32 days of receiving notice.
        Otherwise, all your licenses end immediately.
        
        No Liability
        
        As far as the law allows, the software comes as is,
        without any warranty or condition, and the licensor
        will not be liable to you for any damages arising out
        of these terms or the use or nature of the software,
        under any kind of legal claim.
        
        Definitions
        
        The licensor is the individual or entity offering these
        terms, and the software is the software the licensor
        makes available under these terms.
        
        You refers to the individual or entity agreeing to these
        terms.
        
        Your company is any legal entity, sole proprietorship,
        or other kind of organization that you work for, plus
        all organizations that have control over, are under the
        control of, or are under common control with that
        organization. Control means ownership of substantially
        all the assets of an entity, or the power to direct its
        management and policies by vote, contract, or otherwise.
        Control can be direct or indirect.
        
        Your licenses are all the licenses granted to you for
        the software under these terms.
        
        Use means anything you do with the software requiring
        one of your licenses.
License-File: LICENSE
Keywords: cron,crontab,csv,scheduler,task
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: Other/Proprietary License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
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 :: System :: Systems Administration
Classifier: Topic :: Utilities
Requires-Python: >=3.10
Requires-Dist: croniter>=6.2.2
Provides-Extra: dev
Requires-Dist: pytest-cov>=7.1.0; extra == 'dev'
Requires-Dist: pytest>=9.0.3; extra == 'dev'
Description-Content-Type: text/markdown

<div align="center">
    <img src="docs/logo.png" alt="Logo" width="80" height="80">
</div>

# Crontable

A lightweight Python scheduler that unifies two task types in a single loop:

- **DateTask** — one-shot tasks triggered at a specific datetime, loaded from a semicolon-delimited CSV file
- **CronTask** — repeating tasks driven by standard 5-field cron expressions (or friendly `@aliases`), loaded from a crontab-style text file

Comes with a CLI entry-point and an optional tkinter GUI (`crontable-gui`).

---

## Installation

```bash
pip install crontable
```

Requires Python ≥ 3.10. The only runtime dependency is [`croniter`](https://pypi.org/project/croniter/).

---

## Quick start

### Programmatic usage

```python
from datetime import datetime, timedelta
from crontable import Scheduler, SubprocessExecutor, DateTask, CronTask

executor = SubprocessExecutor()
scheduler = Scheduler(executor=executor, interval=30.0)

scheduler.add_tasks([
    DateTask(
        scheduled_at=datetime.now() + timedelta(minutes=5),
        action="echo 'hello in 5 minutes'",
        name="greeting",
    ),
    CronTask(
        cron_expr="0 9 * * 1-5",
        action="python C:/scripts/daily_report.py",
        name="weekday_report",
    ),
])

try:
    scheduler.run()
except KeyboardInterrupt:
    scheduler.stop()
```

### From a CSV file

```
DATE;NAME;COMMAND
01/01/2027 09:00;morning_report;echo "Good morning"
15/06/2027 14:30;backup;python C:\scripts\backup.py
```

```python
from crontable import FileSource, Scheduler, SubprocessExecutor

source = FileSource("tasks.csv")
scheduler = Scheduler(executor=SubprocessExecutor(), interval=60.0)
scheduler.add_tasks(source.load())
scheduler.run()
```

### From a crontab file

```
# Every weekday at 9 am
0 9 * * 1-5   python C:\scripts\report.py
# French alias — every Monday at midnight
@lundi        echo "Bonne semaine"
```

```python
from crontable import FileSource, Scheduler, SubprocessExecutor

source = FileSource("jobs.txt")
scheduler = Scheduler(executor=SubprocessExecutor(), interval=60.0)
scheduler.add_tasks(source.load())
scheduler.run()
```

### Hot-reload on file change

Pass the source to the scheduler and set `reload_on_change=True`. Every tick,
the scheduler checks `source.has_changed()` and atomically swaps in
`source.load()` when the file is touched. A failing parse (half-saved edit,
invalid syntax) is logged and the previous task list is kept.

```python
source = FileSource("jobs.txt")
scheduler = Scheduler(
    executor=SubprocessExecutor(),
    interval=5.0,
    source=source,
    reload_on_change=True,
)
scheduler.add_tasks(source.load())
scheduler.run()
```

See [examples/](examples/) for more runnable patterns.

---

## CLI

```bash
# Programmatic demo
crontable

# Load from file (auto-detects CSV vs crontab by extension)
crontable tasks.csv
crontable crontab.txt
```

## GUI

```bash
crontable-gui
```

Features: file browser, configurable polling interval, live task list with right-click "Run now", color-coded log, hot-reload on file change, persistent config.

Build a standalone Windows `.exe`:

```bat
scripts\build_exe.bat
```

---

## Supported cron aliases

| Alias                 | Expression          | Alias                  | Expression      |
| --------------------- | ------------------- | ---------------------- | --------------- |
| `@hourly`             | `0 * * * *`         | `@daily` / `@midnight` | `0 0 * * *`     |
| `@weekly`             | `0 0 * * 0`         | `@monthly`             | `0 0 1 * *`     |
| `@annually` / `@year` | `0 0 1 1 *`         | `@noon`                | `0 12 * * *`    |
| `@biweekly`           | `0 0 * * 0,2,4`     | `@bimonthly`           | `0 0 1,15 * *`  |
| `@mon` … `@sun`       | weekday at midnight | `@lundi` … `@dimanche` | French weekdays |

---

## Path aliases in commands

| Alias      | Expands to                 |
| ---------- | -------------------------- |
| `@python`  | Current Python interpreter |
| `@home`    | User home directory        |
| `@desktop` | `~/Desktop`                |

---

## Development

```bash
pip install -e ".[dev]"
pytest
```
