giorgio


Namegiorgio JSON
Version 1.5.6 PyPI version JSON
download
home_pageNone
SummaryGiorgio: a micro-framework for interactive Python scripts
upload_time2025-09-05 15:10:42
maintainerNone
docs_urlNone
authorNone
requires_python<4.0,>=3.10
licenseMIT License Copyright (c) 2025 Danilo Musci · Officina Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
keywords automation cli scripts micro-framework
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage
            # Giorgio - Automation Framework

*A lightweight, extensible micro‑framework for fast, friendly automation scripts.*

<p>
    <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
    <a href="https://pypi.org/project/giorgio">
        <img alt="PyPI Version" src="https://badge.fury.io/py/giorgio.svg"/>
    </a>
    <a href="https://www.python.org/downloads/release/python-380/">
        <img alt="Python Version" src="https://img.shields.io/badge/python-3.10%2B-blue.svg"/>
    </a>
    <a href="https://codecov.io/gh/officinaMusci/giorgio">
        <img alt="Codecov Coverage" src="https://codecov.io/gh/officinaMusci/giorgio/branch/main/graph/badge.svg"/>
    </a>
    <a href="./LICENSE">
        <img alt="License: MIT" src="https://img.shields.io/badge/License-MIT-green.svg"/>
    </a>
</p>

Giorgio helps you scaffold, run, and compose automation scripts—from one‑off utilities to ambitious prototypes—without the ceremony. Think of it as a courteous digital butler: it asks the right questions, remembers your preferences, and carries out your instructions with minimal fuss.

---

## Table of contents

- [Giorgio - Automation Framework](#giorgio---automation-framework)
  - [Table of contents](#table-of-contents)
  - [Why Giorgio?](#why-giorgio)
  - [Features](#features)
  - [Installation](#installation)
  - [Quick start](#quick-start)
    - [Initialize a project](#initialize-a-project)
    - [Scaffold a script](#scaffold-a-script)
    - [Generate a script with AI (vibe‑coding)](#generate-a-script-with-ai-vibecoding)
    - [Run interactively or automatically](#run-interactively-or-automatically)
  - [Project layout](#project-layout)
  - [Script anatomy](#script-anatomy)
    - [1. CONFIG](#1-config)
    - [2. PARAMS](#2-params)
    - [3. `run(context)`](#3-runcontext)
    - [The `Context` API](#the-context-api)
  - [Composing automations](#composing-automations)
  - [Configuration \& environment variables](#configuration--environment-variables)
  - [CLI reference](#cli-reference)
  - [Scheduling (Cron / Task Scheduler)](#scheduling-cron--task-scheduler)
  - [Tips \& best practices](#tips--best-practices)
  - [Contributing](#contributing)
  - [License](#license)

---

## Why Giorgio?

Script files are quick to write—until they aren’t. Once you add parameters, validation, prompts, environment variables, and a touch of UX, the "quick script" becomes an accidental framework. Giorgio gives that structure to you from the start: a clean scaffold, a type‑safe parameter system, an interactive runner, and an optional AI‑powered script generator that turns plain‑language ideas into working code.

**Use Giorgio when you want:**

- Rapid local automations with a consistent shape.
- Interactive runs that ask for what’s missing, or non‑interactive runs suitable for Cron.
- A clear migration path from small scripts to reusable building blocks.
- To generate boilerplate (or whole scripts) from a description using any OpenAI‑compatible API.

## Features

- **Instant scaffolding** with a best‑practice directory layout.
- **Script generator** from templates or via *vibe‑coding* using an OpenAI‑compatible API.
- **Interactive CLI** with dynamic prompts and live output, or **fully automated** runs.
- **Type‑safe parameters** with custom types, choices, and validation.
- **Environment variable** placeholders and `.env` loading.
- **Composable automation**: call other scripts from your script.
- **Pluggable UI renderers** for tailored interactive experiences.
- **Minimal setup, maximum extensibility**: configure only what you need.

## Installation

Giorgio supports **Python 3.10+**. Installing with **pipx** keeps your CLI isolated and on your PATH:

```bash
pipx install giorgio
```

Alternatively, use pip in a virtual environment:

```bash
python -m venv .venv
source .venv/bin/activate  # Windows: .venv\\Scripts\\activate
pip install giorgio
```

> **Note**
> For AI‑powered generation you’ll need an OpenAI‑compatible endpoint and API key (see [Generate a script with AI](#generate-a-script-with-ai-vibe-coding)).

## Quick start

### Initialize a project

```bash
giorgio init my_project
cd my_project
```

Creates a clean structure with dedicated folders for **scripts**, shared **modules**, and configuration.

### Scaffold a script

```bash
giorgio new cleanup_logs
```

This creates `scripts/cleanup_logs/script.py` with a ready‑to‑edit skeleton (`CONFIG`, `PARAMS`, and `run(context)`).

> **Note**
> Scripts can also be created in subdirectories, e.g.:
> 
> ```bash
> giorgio new cleansing/cleanup_logs
> ```
> 
> This will create `scripts/cleansing/cleanup_logs/script.py`.

### Generate a script with AI (vibe‑coding)

```bash
giorgio new greet_user --ai-prompt "Create a script that prints a text provided as a parameter"
```

When using `--ai-prompt`, Giorgio may also ask to include project modules or existing scripts as **context** to improve generation. The result follows Giorgio’s conventions and includes inline documentation.

**Environment** (typical):

You can set environment variables directly in your shell, or place them in your project’s `.env` file (recommended for local development):

```bash
export AI_API_KEY=...
export AI_BASE_URL=https://my-endpoint.example/v1
export AI_API_MODEL=my-favorite-model
export AI_TEMPERATURE=0.2         # (optional) Controls randomness, default 0.0
export AI_MAX_TOKENS=2048         # (optional) Max output tokens, default unlimited
```

Or in `.env`:

```
AI_API_KEY=...
AI_BASE_URL=https://my-endpoint.example/v1
AI_API_MODEL=my-favorite-model
AI_TEMPERATURE=0.2
AI_MAX_TOKENS=2048
```

### Run interactively or automatically

**Interactive mode**: Prompts you to select a script, then asks for parameters.

```bash
giorgio start
```

**Automated (non-interactive) mode**: Runs the specified script directly. You must provide all required parameters (or ensure they have defaults).

```bash
giorgio run cleanup_logs --param days=30 --param log_dir=/var/logs
```

Use interactive mode for guided runs and parameter prompts; use non-interactive mode for automation and scripting (e.g., in Cron jobs).

## Project layout

After `giorgio init my_project`:

```
my_project/
├─ .giorgio/config.json
├─ modules/
│  └─ __init__.py
├─ scripts/
└─ .env
```

<!-- BEGIN GIORGIO_SCRIPT_ANATOMY -->
## Script anatomy

Every Giorgio script follows a standard structure: **CONFIG**, **PARAMS**, and a `run(context)` function.

### 1. CONFIG

`CONFIG` is optional metadata shown in interactive mode.

```python
CONFIG = {
    "name": "Cleanup Logs",
    "description": "Remove old log files from a target directory."
}
```

### 2. PARAMS

`PARAMS` declares **all inputs** the script needs. Giorgio validates types, applies defaults, and—if running interactively—prompts for anything missing.

Supported attributes:

- `type` *(required)* — validates and converts the value (e.g. `str`, `int`, `bool`, `Path`, or custom classes).
- `default` *(optional)* — a fallback value; supports `${VAR_NAME}` placeholders for environment variables.
- `description` *(optional)* — a short help text.
- `choices` *(optional)* — restricts input to a predefined list of values.
- `multiple` *(optional)* — allow selection of multiple values (with `choices`).
- `required` *(optional)* — mark the parameter as mandatory.
- `validation` *(optional)* — a function that returns `True` or an error message.

Example:

```python
from pathlib import Path

PARAMS = {
    "confirm": {
        "type": bool,
        "default": False,
        "description": "Whether to confirm the action.",
    },
    "days": {
        "type": int,
        "default": 30,
        "description": "Delete files older than N days.",
        "validation": lambda x: x > 0 or "Days must be a positive integer."
    },
    "log_dir": {
        "type": Path,
        "description": "Directory containing log files.",
        "required": True
    },
    "level": {
        "type": str,
        "choices": ["debug", "info", "warning", "error"],
        "description": "Logging verbosity.",
    },
    "options": {
        "type": str,
        "choices": ["dry_run", "force"],
        "multiple": True,
        "description": "Optional flags."
    },
    "environment_var": {
        "type": str,
        "default": "${MY_ENV_VAR}",
        "description": "Value read from env if set."
    }
}
```

### 3. `run(context)`

`run(context)` is the script’s entry point. It receives a `Context` object providing everything needed at runtime.

```python
from pathlib import Path
from giorgio.execution_engine import Context, GiorgioCancellationError


def run(context: Context):
    try:
        log_dir: Path = context.params["log_dir"]
        days: int = context.params["days"]

        print(f"Cleaning logs older than {days} days in {log_dir}…")

        # Example of dynamic prompting (interactive mode only)
        context.add_params({
            "confirm": {
                "type": bool,
                "description": "Are you sure you want to delete these files?",
                "default": False,
            }
        })

        if context.params["confirm"]:
            # Compose with another Giorgio script
            context.call_script("delete_files", {"target_dir": log_dir})
            print("Cleanup completed.")
        else:
            print("Operation cancelled.")

    except GiorgioCancellationError:
        print("Script execution cancelled by the user.")
```

### The `Context` API

The `Context` object exposes:

* **Validated parameters** — `context.params["key"]`.
* **Environment variables** — `context.env["VAR"]` (loads from `.env` and the system).
* **Dynamic prompting** — `context.add_params({...})` to ask for more inputs at runtime (interactive mode only).
* **Composition** — `context.call_script(name, params)` to run other Giorgio scripts programmatically.
* **Logging & output** — standard `print()` works; advanced loggers can be wired by UI renderers.
<!-- END GIORGIO_SCRIPT_ANATOMY -->

## Composing automations

Scripts are building blocks. You can invoke one script from another to create small, readable steps that add up to robust flows.

```python
def run(context):
    # Normalize inputs in one script…
    context.call_script("normalize_dataset", {"src": "./raw.csv"})
    # …then pass results into the next one.
    context.call_script("train_model", {"epochs": 10, "lr": 0.001})
```

Composition keeps each script focused and testable while enabling richer automations.

## Configuration & environment variables

Giorgio reads environment variables from the OS and, if present, from a local `.env` file at project root. Within `PARAMS`, you may reference variables using `${VAR_NAME}` in `default` values; these expand at runtime.

**Supported AI environment variables:**

- `AI_API_KEY` — API key for your OpenAI-compatible endpoint (**required**)
- `AI_BASE_URL` — Base URL for the API (**required**)
- `AI_MODEL` or `AI_API_MODEL` — Model name (**required**)
- `AI_TEMPERATURE` — *(optional)* Controls randomness (float, default: 0.0)
- `AI_MAX_TOKENS` — *(optional)* Maximum output tokens (int, default: unlimited)

Example `.env`:

```
DATA_DIR=./data
MY_ENV_VAR=hello
```

Example `PARAMS` default using an env placeholder:

```python
"data_dir": {
    "type": Path,
    "default": "${DATA_DIR}",
    "description": "Where datasets are stored."
}
```

## CLI reference

```
giorgio init <project_name>
    Create a new Giorgio project (folders for scripts, modules, config).

giorgio new <script_name> [--ai-prompt "…"]
    Scaffold a new script. With --ai-prompt, generate code via an OpenAI‑compatible API.

giorgio start
    Launch interactive mode. Select a script; Giorgio prompts for missing params.

giorgio run <script_name> --param key=value [--param key=value ...]
    Run non‑interactively (suitable for Cron). Provide all required params.

giorgio --help
    Show general help and options.
```

> **Tip**
> Use `--param` repeatedly to pass multiple key/value pairs.

## Scheduling (Cron / Task Scheduler)

**Cron (Linux/macOS):**

```
# Run every night at 02:30
30 2 * * * cd /path/to/my_project && /usr/bin/env giorgio run cleanup_logs \
  --param days=30 --param log_dir=/var/logs >> cron.log 2>&1
```

**Windows Task Scheduler:** create a task that executes:

```
C:\\Path\\To\\Python\\Scripts\\giorgio.exe run cleanup_logs --param days=30 --param log_dir=C:\\Logs
```

## Tips & best practices
- **Keep scripts small and focused.** Compose multiple scripts for larger automation flows to maximize clarity and reusability.
- **Declare all inputs in `PARAMS`.** Avoid using implicit globals; explicit parameters improve validation and documentation.
- **Leverage `choices` and `validation`.** Define allowed values and validation logic to catch errors early and guide users.
- **Encapsulate reusable logic in `modules/`.** Place shared functions and utilities in the `modules/` directory and import them into your scripts.
- **Use `context.add_params()` for dynamic prompting.** Prefer Giorgio’s built-in parameter prompting over other package methods or native Python functions like `input()`. This ensures consistent UX, validation, and compatibility with both interactive and automated runs.
- **Reserve AI generation for boilerplate or drafts.** Use AI-powered script generation to accelerate prototyping, but always review and refine generated code before use.
- **Handle secrets securely.** Store API keys and sensitive data in your `.env` file (excluded from version control) or your OS keychain—never hard-code them.
- **Review AI-generated code before production use.** Always inspect and test code generated by AI before deploying in critical environments.
- **Avoid logging secrets.** Redact or exclude sensitive information from logs to prevent accidental exposure.

## Contributing

Community contributions are welcome and encouraged. To maintain a smooth and manageable workflow, please adhere to the following guidelines.

Development follows a trunk-based workflow using short-lived branches created from `main`. When your changes are complete and stable, open a pull request (PR) targeting `main`. This approach ensures the codebase remains up-to-date and avoids long-lived branches.

Please write commit messages according to the [Conventional Commits](https://www.conventionalcommits.org/) specification. To make this easier, use the [commitizen](https://commitizen-tools.github.io/commitizen/) tool, which helps you generate properly formatted commit messages. You can run `cz commit` instead of `git commit` to be guided through the process.

All pull requests against `main` trigger the [CI workflow](./.github/workflows/ci.yml), which runs linting, tests across Python 3.10–3.12 on Linux, macOS, and Windows, and enforces the coverage threshold. After a push to the `main` branch, the [version bump workflow](./.github/workflows/bump.yml) runs to bump the version with Commitizen and update `CHANGELOG.md`, pushing the new `v*` tag. Pushing that tag then triggers the [publish workflow](./.github/workflows/publish.yml) to run final tests & coverage upload, build the distribution, and publish the package to PyPI.

**Please ensure that every contribution includes appropriate tests.** Adding or updating tests helps maintain code quality and reliability for all users.

Thank you for contributing to Giorgio!

## License

This project is licensed under the terms of the [MIT License](./LICENSE). Refer to the `LICENSE` file for full license text.

---

*Happy automating with Giorgio!*

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "giorgio",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4.0,>=3.10",
    "maintainer_email": null,
    "keywords": "automation, cli, scripts, micro-framework",
    "author": null,
    "author_email": "Danilo Musci <officina@musci.ch>",
    "download_url": "https://files.pythonhosted.org/packages/81/fb/e88ef742b86d7bf78487254e1270106ff516598e5c5b6d680fe26f9efd53/giorgio-1.5.6.tar.gz",
    "platform": null,
    "description": "# Giorgio - Automation Framework\n\n*A lightweight, extensible micro\u2011framework for fast, friendly automation scripts.*\n\n<p>\n    <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->\n    <a href=\"https://pypi.org/project/giorgio\">\n        <img alt=\"PyPI Version\" src=\"https://badge.fury.io/py/giorgio.svg\"/>\n    </a>\n    <a href=\"https://www.python.org/downloads/release/python-380/\">\n        <img alt=\"Python Version\" src=\"https://img.shields.io/badge/python-3.10%2B-blue.svg\"/>\n    </a>\n    <a href=\"https://codecov.io/gh/officinaMusci/giorgio\">\n        <img alt=\"Codecov Coverage\" src=\"https://codecov.io/gh/officinaMusci/giorgio/branch/main/graph/badge.svg\"/>\n    </a>\n    <a href=\"./LICENSE\">\n        <img alt=\"License: MIT\" src=\"https://img.shields.io/badge/License-MIT-green.svg\"/>\n    </a>\n</p>\n\nGiorgio helps you scaffold, run, and compose automation scripts\u2014from one\u2011off utilities to ambitious prototypes\u2014without the ceremony. Think of it as a courteous digital butler: it asks the right questions, remembers your preferences, and carries out your instructions with minimal fuss.\n\n---\n\n## Table of contents\n\n- [Giorgio - Automation Framework](#giorgio---automation-framework)\n  - [Table of contents](#table-of-contents)\n  - [Why Giorgio?](#why-giorgio)\n  - [Features](#features)\n  - [Installation](#installation)\n  - [Quick start](#quick-start)\n    - [Initialize a project](#initialize-a-project)\n    - [Scaffold a script](#scaffold-a-script)\n    - [Generate a script with AI (vibe\u2011coding)](#generate-a-script-with-ai-vibecoding)\n    - [Run interactively or automatically](#run-interactively-or-automatically)\n  - [Project layout](#project-layout)\n  - [Script anatomy](#script-anatomy)\n    - [1. CONFIG](#1-config)\n    - [2. PARAMS](#2-params)\n    - [3. `run(context)`](#3-runcontext)\n    - [The `Context` API](#the-context-api)\n  - [Composing automations](#composing-automations)\n  - [Configuration \\& environment variables](#configuration--environment-variables)\n  - [CLI reference](#cli-reference)\n  - [Scheduling (Cron / Task Scheduler)](#scheduling-cron--task-scheduler)\n  - [Tips \\& best practices](#tips--best-practices)\n  - [Contributing](#contributing)\n  - [License](#license)\n\n---\n\n## Why Giorgio?\n\nScript files are quick to write\u2014until they aren\u2019t. Once you add parameters, validation, prompts, environment variables, and a touch of UX, the \"quick script\" becomes an accidental framework. Giorgio gives that structure to you from the start: a clean scaffold, a type\u2011safe parameter system, an interactive runner, and an optional AI\u2011powered script generator that turns plain\u2011language ideas into working code.\n\n**Use Giorgio when you want:**\n\n- Rapid local automations with a consistent shape.\n- Interactive runs that ask for what\u2019s missing, or non\u2011interactive runs suitable for Cron.\n- A clear migration path from small scripts to reusable building blocks.\n- To generate boilerplate (or whole scripts) from a description using any OpenAI\u2011compatible API.\n\n## Features\n\n- **Instant scaffolding** with a best\u2011practice directory layout.\n- **Script generator** from templates or via *vibe\u2011coding* using an OpenAI\u2011compatible API.\n- **Interactive CLI** with dynamic prompts and live output, or **fully automated** runs.\n- **Type\u2011safe parameters** with custom types, choices, and validation.\n- **Environment variable** placeholders and `.env` loading.\n- **Composable automation**: call other scripts from your script.\n- **Pluggable UI renderers** for tailored interactive experiences.\n- **Minimal setup, maximum extensibility**: configure only what you need.\n\n## Installation\n\nGiorgio supports **Python 3.10+**. Installing with **pipx** keeps your CLI isolated and on your PATH:\n\n```bash\npipx install giorgio\n```\n\nAlternatively, use pip in a virtual environment:\n\n```bash\npython -m venv .venv\nsource .venv/bin/activate  # Windows: .venv\\\\Scripts\\\\activate\npip install giorgio\n```\n\n> **Note**\n> For AI\u2011powered generation you\u2019ll need an OpenAI\u2011compatible endpoint and API key (see [Generate a script with AI](#generate-a-script-with-ai-vibe-coding)).\n\n## Quick start\n\n### Initialize a project\n\n```bash\ngiorgio init my_project\ncd my_project\n```\n\nCreates a clean structure with dedicated folders for **scripts**, shared **modules**, and configuration.\n\n### Scaffold a script\n\n```bash\ngiorgio new cleanup_logs\n```\n\nThis creates `scripts/cleanup_logs/script.py` with a ready\u2011to\u2011edit skeleton (`CONFIG`, `PARAMS`, and `run(context)`).\n\n> **Note**\n> Scripts can also be created in subdirectories, e.g.:\n> \n> ```bash\n> giorgio new cleansing/cleanup_logs\n> ```\n> \n> This will create `scripts/cleansing/cleanup_logs/script.py`.\n\n### Generate a script with AI (vibe\u2011coding)\n\n```bash\ngiorgio new greet_user --ai-prompt \"Create a script that prints a text provided as a parameter\"\n```\n\nWhen using `--ai-prompt`, Giorgio may also ask to include project modules or existing scripts as **context** to improve generation. The result follows Giorgio\u2019s conventions and includes inline documentation.\n\n**Environment** (typical):\n\nYou can set environment variables directly in your shell, or place them in your project\u2019s `.env` file (recommended for local development):\n\n```bash\nexport AI_API_KEY=...\nexport AI_BASE_URL=https://my-endpoint.example/v1\nexport AI_API_MODEL=my-favorite-model\nexport AI_TEMPERATURE=0.2         # (optional) Controls randomness, default 0.0\nexport AI_MAX_TOKENS=2048         # (optional) Max output tokens, default unlimited\n```\n\nOr in `.env`:\n\n```\nAI_API_KEY=...\nAI_BASE_URL=https://my-endpoint.example/v1\nAI_API_MODEL=my-favorite-model\nAI_TEMPERATURE=0.2\nAI_MAX_TOKENS=2048\n```\n\n### Run interactively or automatically\n\n**Interactive mode**: Prompts you to select a script, then asks for parameters.\n\n```bash\ngiorgio start\n```\n\n**Automated (non-interactive) mode**: Runs the specified script directly. You must provide all required parameters (or ensure they have defaults).\n\n```bash\ngiorgio run cleanup_logs --param days=30 --param log_dir=/var/logs\n```\n\nUse interactive mode for guided runs and parameter prompts; use non-interactive mode for automation and scripting (e.g., in Cron jobs).\n\n## Project layout\n\nAfter `giorgio init my_project`:\n\n```\nmy_project/\n\u251c\u2500 .giorgio/config.json\n\u251c\u2500 modules/\n\u2502  \u2514\u2500 __init__.py\n\u251c\u2500 scripts/\n\u2514\u2500 .env\n```\n\n<!-- BEGIN GIORGIO_SCRIPT_ANATOMY -->\n## Script anatomy\n\nEvery Giorgio script follows a standard structure: **CONFIG**, **PARAMS**, and a `run(context)` function.\n\n### 1. CONFIG\n\n`CONFIG` is optional metadata shown in interactive mode.\n\n```python\nCONFIG = {\n    \"name\": \"Cleanup Logs\",\n    \"description\": \"Remove old log files from a target directory.\"\n}\n```\n\n### 2. PARAMS\n\n`PARAMS` declares **all inputs** the script needs. Giorgio validates types, applies defaults, and\u2014if running interactively\u2014prompts for anything missing.\n\nSupported attributes:\n\n- `type` *(required)* \u2014 validates and converts the value (e.g. `str`, `int`, `bool`, `Path`, or custom classes).\n- `default` *(optional)* \u2014 a fallback value; supports `${VAR_NAME}` placeholders for environment variables.\n- `description` *(optional)* \u2014 a short help text.\n- `choices` *(optional)* \u2014 restricts input to a predefined list of values.\n- `multiple` *(optional)* \u2014 allow selection of multiple values (with `choices`).\n- `required` *(optional)* \u2014 mark the parameter as mandatory.\n- `validation` *(optional)* \u2014 a function that returns `True` or an error message.\n\nExample:\n\n```python\nfrom pathlib import Path\n\nPARAMS = {\n    \"confirm\": {\n        \"type\": bool,\n        \"default\": False,\n        \"description\": \"Whether to confirm the action.\",\n    },\n    \"days\": {\n        \"type\": int,\n        \"default\": 30,\n        \"description\": \"Delete files older than N days.\",\n        \"validation\": lambda x: x > 0 or \"Days must be a positive integer.\"\n    },\n    \"log_dir\": {\n        \"type\": Path,\n        \"description\": \"Directory containing log files.\",\n        \"required\": True\n    },\n    \"level\": {\n        \"type\": str,\n        \"choices\": [\"debug\", \"info\", \"warning\", \"error\"],\n        \"description\": \"Logging verbosity.\",\n    },\n    \"options\": {\n        \"type\": str,\n        \"choices\": [\"dry_run\", \"force\"],\n        \"multiple\": True,\n        \"description\": \"Optional flags.\"\n    },\n    \"environment_var\": {\n        \"type\": str,\n        \"default\": \"${MY_ENV_VAR}\",\n        \"description\": \"Value read from env if set.\"\n    }\n}\n```\n\n### 3. `run(context)`\n\n`run(context)` is the script\u2019s entry point. It receives a `Context` object providing everything needed at runtime.\n\n```python\nfrom pathlib import Path\nfrom giorgio.execution_engine import Context, GiorgioCancellationError\n\n\ndef run(context: Context):\n    try:\n        log_dir: Path = context.params[\"log_dir\"]\n        days: int = context.params[\"days\"]\n\n        print(f\"Cleaning logs older than {days} days in {log_dir}\u2026\")\n\n        # Example of dynamic prompting (interactive mode only)\n        context.add_params({\n            \"confirm\": {\n                \"type\": bool,\n                \"description\": \"Are you sure you want to delete these files?\",\n                \"default\": False,\n            }\n        })\n\n        if context.params[\"confirm\"]:\n            # Compose with another Giorgio script\n            context.call_script(\"delete_files\", {\"target_dir\": log_dir})\n            print(\"Cleanup completed.\")\n        else:\n            print(\"Operation cancelled.\")\n\n    except GiorgioCancellationError:\n        print(\"Script execution cancelled by the user.\")\n```\n\n### The `Context` API\n\nThe `Context` object exposes:\n\n* **Validated parameters** \u2014 `context.params[\"key\"]`.\n* **Environment variables** \u2014 `context.env[\"VAR\"]` (loads from `.env` and the system).\n* **Dynamic prompting** \u2014 `context.add_params({...})` to ask for more inputs at runtime (interactive mode only).\n* **Composition** \u2014 `context.call_script(name, params)` to run other Giorgio scripts programmatically.\n* **Logging & output** \u2014 standard `print()` works; advanced loggers can be wired by UI renderers.\n<!-- END GIORGIO_SCRIPT_ANATOMY -->\n\n## Composing automations\n\nScripts are building blocks. You can invoke one script from another to create small, readable steps that add up to robust flows.\n\n```python\ndef run(context):\n    # Normalize inputs in one script\u2026\n    context.call_script(\"normalize_dataset\", {\"src\": \"./raw.csv\"})\n    # \u2026then pass results into the next one.\n    context.call_script(\"train_model\", {\"epochs\": 10, \"lr\": 0.001})\n```\n\nComposition keeps each script focused and testable while enabling richer automations.\n\n## Configuration & environment variables\n\nGiorgio reads environment variables from the OS and, if present, from a local `.env` file at project root. Within `PARAMS`, you may reference variables using `${VAR_NAME}` in `default` values; these expand at runtime.\n\n**Supported AI environment variables:**\n\n- `AI_API_KEY` \u2014 API key for your OpenAI-compatible endpoint (**required**)\n- `AI_BASE_URL` \u2014 Base URL for the API (**required**)\n- `AI_MODEL` or `AI_API_MODEL` \u2014 Model name (**required**)\n- `AI_TEMPERATURE` \u2014 *(optional)* Controls randomness (float, default: 0.0)\n- `AI_MAX_TOKENS` \u2014 *(optional)* Maximum output tokens (int, default: unlimited)\n\nExample `.env`:\n\n```\nDATA_DIR=./data\nMY_ENV_VAR=hello\n```\n\nExample `PARAMS` default using an env placeholder:\n\n```python\n\"data_dir\": {\n    \"type\": Path,\n    \"default\": \"${DATA_DIR}\",\n    \"description\": \"Where datasets are stored.\"\n}\n```\n\n## CLI reference\n\n```\ngiorgio init <project_name>\n    Create a new Giorgio project (folders for scripts, modules, config).\n\ngiorgio new <script_name> [--ai-prompt \"\u2026\"]\n    Scaffold a new script. With --ai-prompt, generate code via an OpenAI\u2011compatible API.\n\ngiorgio start\n    Launch interactive mode. Select a script; Giorgio prompts for missing params.\n\ngiorgio run <script_name> --param key=value [--param key=value ...]\n    Run non\u2011interactively (suitable for Cron). Provide all required params.\n\ngiorgio --help\n    Show general help and options.\n```\n\n> **Tip**\n> Use `--param` repeatedly to pass multiple key/value pairs.\n\n## Scheduling (Cron / Task Scheduler)\n\n**Cron (Linux/macOS):**\n\n```\n# Run every night at 02:30\n30 2 * * * cd /path/to/my_project && /usr/bin/env giorgio run cleanup_logs \\\n  --param days=30 --param log_dir=/var/logs >> cron.log 2>&1\n```\n\n**Windows Task Scheduler:** create a task that executes:\n\n```\nC:\\\\Path\\\\To\\\\Python\\\\Scripts\\\\giorgio.exe run cleanup_logs --param days=30 --param log_dir=C:\\\\Logs\n```\n\n## Tips & best practices\n- **Keep scripts small and focused.** Compose multiple scripts for larger automation flows to maximize clarity and reusability.\n- **Declare all inputs in `PARAMS`.** Avoid using implicit globals; explicit parameters improve validation and documentation.\n- **Leverage `choices` and `validation`.** Define allowed values and validation logic to catch errors early and guide users.\n- **Encapsulate reusable logic in `modules/`.** Place shared functions and utilities in the `modules/` directory and import them into your scripts.\n- **Use `context.add_params()` for dynamic prompting.** Prefer Giorgio\u2019s built-in parameter prompting over other package methods or native Python functions like `input()`. This ensures consistent UX, validation, and compatibility with both interactive and automated runs.\n- **Reserve AI generation for boilerplate or drafts.** Use AI-powered script generation to accelerate prototyping, but always review and refine generated code before use.\n- **Handle secrets securely.** Store API keys and sensitive data in your `.env` file (excluded from version control) or your OS keychain\u2014never hard-code them.\n- **Review AI-generated code before production use.** Always inspect and test code generated by AI before deploying in critical environments.\n- **Avoid logging secrets.** Redact or exclude sensitive information from logs to prevent accidental exposure.\n\n## Contributing\n\nCommunity contributions are welcome and encouraged. To maintain a smooth and manageable workflow, please adhere to the following guidelines.\n\nDevelopment follows a trunk-based workflow using short-lived branches created from `main`. When your changes are complete and stable, open a pull request (PR) targeting `main`. This approach ensures the codebase remains up-to-date and avoids long-lived branches.\n\nPlease write commit messages according to the [Conventional Commits](https://www.conventionalcommits.org/) specification. To make this easier, use the [commitizen](https://commitizen-tools.github.io/commitizen/) tool, which helps you generate properly formatted commit messages. You can run `cz commit` instead of `git commit` to be guided through the process.\n\nAll pull requests against `main` trigger the [CI workflow](./.github/workflows/ci.yml), which runs linting, tests across Python 3.10\u20133.12 on Linux, macOS, and Windows, and enforces the coverage threshold. After a push to the `main` branch, the [version bump workflow](./.github/workflows/bump.yml) runs to bump the version with Commitizen and update `CHANGELOG.md`, pushing the new `v*` tag. Pushing that tag then triggers the [publish workflow](./.github/workflows/publish.yml) to run final tests & coverage upload, build the distribution, and publish the package to PyPI.\n\n**Please ensure that every contribution includes appropriate tests.** Adding or updating tests helps maintain code quality and reliability for all users.\n\nThank you for contributing to Giorgio!\n\n## License\n\nThis project is licensed under the terms of the [MIT License](./LICENSE). Refer to the `LICENSE` file for full license text.\n\n---\n\n*Happy automating with Giorgio!*\n",
    "bugtrack_url": null,
    "license": "MIT License\n        \n        Copyright (c) 2025 Danilo Musci \u00b7 Officina\n        \n        Permission is hereby granted, free of charge, to any person obtaining a copy\n        of this software and associated documentation files (the \"Software\"), to deal\n        in the Software without restriction, including without limitation the rights\n        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n        copies of the Software, and to permit persons to whom the Software is\n        furnished to do so, subject to the following conditions:\n        \n        The above copyright notice and this permission notice shall be included in all\n        copies or substantial portions of the Software.\n        \n        THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n        SOFTWARE.\n        ",
    "summary": "Giorgio: a micro-framework for interactive Python scripts",
    "version": "1.5.6",
    "project_urls": {
        "Changelog": "https://github.com/officinaMusci/giorgio/blob/master/CHANGELOG.md",
        "Documentation": "https://github.com/officinaMusci/giorgio#readme",
        "Homepage": "https://github.com/officinaMusci/giorgio",
        "Issues": "https://github.com/officinaMusci/giorgio/issues",
        "Repository": "https://github.com/officinaMusci/giorgio"
    },
    "split_keywords": [
        "automation",
        " cli",
        " scripts",
        " micro-framework"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "eae43c6e1f438c7b9a9c42714263f3edc0246be3631aed2c619179ef4c128af2",
                "md5": "3670221121234dd9eede8b570fc2acbe",
                "sha256": "c096c21fb38ecee0f0583e7f6a8cdea68ac567ac0a7a5fa72d44be9e9359268d"
            },
            "downloads": -1,
            "filename": "giorgio-1.5.6-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "3670221121234dd9eede8b570fc2acbe",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4.0,>=3.10",
            "size": 39334,
            "upload_time": "2025-09-05T15:10:40",
            "upload_time_iso_8601": "2025-09-05T15:10:40.962980Z",
            "url": "https://files.pythonhosted.org/packages/ea/e4/3c6e1f438c7b9a9c42714263f3edc0246be3631aed2c619179ef4c128af2/giorgio-1.5.6-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "81fbe88ef742b86d7bf78487254e1270106ff516598e5c5b6d680fe26f9efd53",
                "md5": "91aecc7d638c454ccc6163582716f1d1",
                "sha256": "84831bc0cf4697f954acf5b933aa72fd2049eb3b2c700dd4e8296430172cbf13"
            },
            "downloads": -1,
            "filename": "giorgio-1.5.6.tar.gz",
            "has_sig": false,
            "md5_digest": "91aecc7d638c454ccc6163582716f1d1",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0,>=3.10",
            "size": 45665,
            "upload_time": "2025-09-05T15:10:42",
            "upload_time_iso_8601": "2025-09-05T15:10:42.052341Z",
            "url": "https://files.pythonhosted.org/packages/81/fb/e88ef742b86d7bf78487254e1270106ff516598e5c5b6d680fe26f9efd53/giorgio-1.5.6.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-09-05 15:10:42",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "officinaMusci",
    "github_project": "giorgio",
    "travis_ci": false,
    "coveralls": true,
    "github_actions": true,
    "lcname": "giorgio"
}
        
Elapsed time: 3.63141s