giorgio


Namegiorgio JSON
Version 1.4.0 PyPI version JSON
download
home_pageNone
SummaryGiorgio: a micro-framework for interactive Python scripts
upload_time2025-07-11 08:50:07
maintainerNone
docs_urlNone
authorNone
requires_python<4.0,>=3.8
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

<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.8%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 is a lightweight, extensible Python micro-framework designed to scaffold, execute, and manage automation scripts. It offers both interactive and automated modes, supports dynamic parameter prompts, and features pluggable UI renderers for a customizable experience—all with minimal setup and boilerplate.

## Features

- **Instant project scaffolding** with a best-practice directory layout.
- **Script generator** for rapid creation of parameterized automation scripts.
- **Flexible execution modes**: interactive CLI with dynamic prompts and live output, or fully automated runs.
- **Type-safe parameter system** supporting custom types, validation, and runtime parameter requests.
- **Seamless environment variable support** for dynamic configuration.
- **Composable automation**: easily invoke scripts from within other scripts.
- **Pluggable UI renderers** for customizing the interactive experience.
- **Minimal setup, maximum extensibility**—configure only what you need.

## Installation

Install Giorgio from PyPI:

```bash
pip install giorgio
```

For local development, consider cloning the repository and installing in editable mode:

```bash
git clone https://github.com/officinaMusci/giorgio.git
cd giorgio
pip install -e .
```

> ⚠️ Ensure your environment meets **Python ≥ 3.8**.

## Quick Start

### 1. Initialize a Project

To kickstart your Giorgio project, run the following command in your terminal:

```bash
giorgio init [--name PATH] # Defaults to current directory
```

When you initialize a project, Giorgio sets up the recommended directory structure and essential files for you. It automatically generates an empty `.env` file for environment variables, along with a `.giorgio/config.json` file pre-populated with default settings, ensuring your project is ready for immediate development.

This command creates the following structure:

```text
.
├── .env               # Optional environment variables (loaded on run/start)
├── scripts/           # Your automation scripts
├── modules/           # Shared Python modules for cross-script reuse
└── .giorgio/          # Giorgio metadata (config.json)
    └── config.json    # Tracks project version, module paths, etc.
```

### 2. Scaffold a New Script

To create a new automation script, use the `new` command followed by your desired script name:

```bash
giorgio new my_script
```

When you scaffold a new script, Giorgio automatically creates a `scripts/my_script/` directory containing a starter `script.py` file. This file comes pre-populated with boilerplate sections for **CONFIG** and **PARAMS**, as well as a stubbed `run()` function, giving you a ready-to-edit foundation for your automation logic.

#### Script Development Guide

Your script should follow a specific structure to ensure compatibility with Giorgio's execution model. Here's a breakdown of the required components:

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

CONFIG = {
    "name": "My Script",
    "description": ""
}

PARAMS = { }


def run(context: Context):
    try:
        # Your script logic goes here
        print("Running the script...")
    
    except GiorgioCancellationError:
        print("Execution was cancelled by the user.")
```

##### `CONFIG` (optional)

The `CONFIG` section allows you to define metadata for your script, such as its name and description. This information is used in the interactive UI to help users understand what the script does.

##### `PARAMS` (required)

The `PARAMS` section defines all the parameters your script requires. Each parameter can specify its `type`, `default` value, `description`, and optional `validation` logic. Giorgio supports standard Python types (`str`, `int`, `float`, `bool`, `Path`) as well as custom classes—if you provide a custom type, Giorgio will instantiate it using the supplied value.

You can enhance parameters with:

- **default**: Sets a fallback value if none is provided. Supports static values or environment variable placeholders using `${VAR_NAME}` syntax, which are resolved from your `.env` file at runtime.
- **choices**: Restricts input to a predefined list of valid options.
- **multiple**: (used with `choices`) Allows users to select more than one option.

Custom validation is supported via a `validation` function that returns `True` or an error message.

This flexible system ensures your scripts are type-safe, user-friendly, and easily configurable for both interactive and automated workflows.

```python
PARAMS = {
    "confirm": {
        "type": bool,
        "default": False,
        "description": "Whether to confirm the action.",
    },
    "count": {
        "type": int,
        "default": 1,
        "description": "Number of times to repeat the action.",
        "validation": lambda x: x > 0 or "Count must be a positive integer."
    },
    "path": {
        "type": Path,
        "description": "Path to your file.",
        "required": True
    },
    "options": {
        "type": str,
        "choices": ["optA", "optB", "optC", "optD"],
        "description": "Select one or more options.",
        "multiple": True
    },
    "custom": {
        "type": MyCustomClass,
        "description": "An instance of MyCustomClass.",
    },
    "environment_var": {
        "type": str,
        "default": "${MY_ENV_VAR}",
        "description": "An environment variable value.",
    }
}
```

##### `run(context)`

The `run(context)` function serves as the main entry point for your script. It receives a `Context` object, which provides convenient access to everything your script needs:

- **Parameter values:** Retrieve user-supplied or defaulted parameters via `context.params`.
- **Environment variables:** Access environment variables loaded from `.env` or the system using `context.env`.
- **Dynamic parameter prompting:** Use `context.add_params()` to request additional input from the user at runtime (available only in interactive mode).
- **Script composition:** Invoke other Giorgio scripts programmatically with `context.call_script()`.

This design enables your scripts to be both flexible and composable, supporting interactive workflows and automation scenarios with minimal boilerplate.

```python
def run(context):
    try:
        # Get the path parameter
        path: Path = context.params["path"]

        # Grab an environment variable (or fall back to a default)
        username = context.env.get("USER", "mysterious_automator")
        print(f"👋 Hello, {username}! Let's see what's in {path}...")

        # Find all .txt files and prompt the user to pick their favorite
        context.add_params({
            "favorite_file": {
                "type": Path,
                "description": "Which text file deserves your attention today?",
                "choices": txt_files,
                "required": True
            }
        })
        favorite = context.params["favorite_file"]
        print(f"🎉 You picked: {favorite.name}")

        # Call another script to celebrate
        context.call_script("celebrate_file", {"file": favorite})

    except GiorgioCancellationError:
        print("🚨 Script execution cancelled! Maybe next time...")
```

### 3. Run Scripts

#### Non-interactive (for automation):

To execute your script non-interactively, you can use the `run` command followed by the script name and any required parameters:

```bash
giorgio run my_script \
  --param input_file=./data.txt \
  --param count=5
```

All required parameters must be provided when running scripts non-interactively. The command supports boolean flags, lists, and allows you to use environment variable placeholders (such as `${VAR}`) as default values for parameters.

#### Interactive (exploratory):

For an interactive experience, start Giorgio in interactive mode:

```bash
giorgio start [--ui RENDERER]
```

When running in interactive mode, Giorgio presents a menu of available scripts and guides you through each required parameter, providing validation, default values, and helpful descriptions. Output from your script is streamed live to your terminal, and you can safely abort execution with Ctrl+C.

Giorgio supports **pluggable UI renderers** for interactive mode. By default, the CLI renderer is used, but you can specify another renderer with the `--ui` option if additional renderers are installed. To see available renderers, run:

```bash
giorgio start --help
```

To add new UI renderers (such as a GUI or web interface), install a compatible plugin that registers itself under the `giorgio.ui_renderers` entry point. Once installed, the new renderer will be available for selection via the `--ui` flag.

This extensibility allows you to tailor the interactive experience to your workflow, whether you prefer a classic terminal UI or a custom interface.

## 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.8–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.8",
    "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/b4/58/47f7eed6a58633fe5148928897091176935cd80bd8f1f5af7d64d78d8f96/giorgio-1.4.0.tar.gz",
    "platform": null,
    "description": "# Giorgio - Automation Framework\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.8%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 is a lightweight, extensible Python micro-framework designed to scaffold, execute, and manage automation scripts. It offers both interactive and automated modes, supports dynamic parameter prompts, and features pluggable UI renderers for a customizable experience\u2014all with minimal setup and boilerplate.\n\n## Features\n\n- **Instant project scaffolding** with a best-practice directory layout.\n- **Script generator** for rapid creation of parameterized automation scripts.\n- **Flexible execution modes**: interactive CLI with dynamic prompts and live output, or fully automated runs.\n- **Type-safe parameter system** supporting custom types, validation, and runtime parameter requests.\n- **Seamless environment variable support** for dynamic configuration.\n- **Composable automation**: easily invoke scripts from within other scripts.\n- **Pluggable UI renderers** for customizing the interactive experience.\n- **Minimal setup, maximum extensibility**\u2014configure only what you need.\n\n## Installation\n\nInstall Giorgio from PyPI:\n\n```bash\npip install giorgio\n```\n\nFor local development, consider cloning the repository and installing in editable mode:\n\n```bash\ngit clone https://github.com/officinaMusci/giorgio.git\ncd giorgio\npip install -e .\n```\n\n> \u26a0\ufe0f Ensure your environment meets **Python \u2265 3.8**.\n\n## Quick Start\n\n### 1. Initialize a Project\n\nTo kickstart your Giorgio project, run the following command in your terminal:\n\n```bash\ngiorgio init [--name PATH] # Defaults to current directory\n```\n\nWhen you initialize a project, Giorgio sets up the recommended directory structure and essential files for you. It automatically generates an empty `.env` file for environment variables, along with a `.giorgio/config.json` file pre-populated with default settings, ensuring your project is ready for immediate development.\n\nThis command creates the following structure:\n\n```text\n.\n\u251c\u2500\u2500 .env               # Optional environment variables (loaded on run/start)\n\u251c\u2500\u2500 scripts/           # Your automation scripts\n\u251c\u2500\u2500 modules/           # Shared Python modules for cross-script reuse\n\u2514\u2500\u2500 .giorgio/          # Giorgio metadata (config.json)\n    \u2514\u2500\u2500 config.json    # Tracks project version, module paths, etc.\n```\n\n### 2. Scaffold a New Script\n\nTo create a new automation script, use the `new` command followed by your desired script name:\n\n```bash\ngiorgio new my_script\n```\n\nWhen you scaffold a new script, Giorgio automatically creates a `scripts/my_script/` directory containing a starter `script.py` file. This file comes pre-populated with boilerplate sections for **CONFIG** and **PARAMS**, as well as a stubbed `run()` function, giving you a ready-to-edit foundation for your automation logic.\n\n#### Script Development Guide\n\nYour script should follow a specific structure to ensure compatibility with Giorgio's execution model. Here's a breakdown of the required components:\n\n```python\nfrom giorgio.execution_engine import Context, GiorgioCancellationError\n\nCONFIG = {\n    \"name\": \"My Script\",\n    \"description\": \"\"\n}\n\nPARAMS = { }\n\n\ndef run(context: Context):\n    try:\n        # Your script logic goes here\n        print(\"Running the script...\")\n    \n    except GiorgioCancellationError:\n        print(\"Execution was cancelled by the user.\")\n```\n\n##### `CONFIG` (optional)\n\nThe `CONFIG` section allows you to define metadata for your script, such as its name and description. This information is used in the interactive UI to help users understand what the script does.\n\n##### `PARAMS` (required)\n\nThe `PARAMS` section defines all the parameters your script requires. Each parameter can specify its `type`, `default` value, `description`, and optional `validation` logic. Giorgio supports standard Python types (`str`, `int`, `float`, `bool`, `Path`) as well as custom classes\u2014if you provide a custom type, Giorgio will instantiate it using the supplied value.\n\nYou can enhance parameters with:\n\n- **default**: Sets a fallback value if none is provided. Supports static values or environment variable placeholders using `${VAR_NAME}` syntax, which are resolved from your `.env` file at runtime.\n- **choices**: Restricts input to a predefined list of valid options.\n- **multiple**: (used with `choices`) Allows users to select more than one option.\n\nCustom validation is supported via a `validation` function that returns `True` or an error message.\n\nThis flexible system ensures your scripts are type-safe, user-friendly, and easily configurable for both interactive and automated workflows.\n\n```python\nPARAMS = {\n    \"confirm\": {\n        \"type\": bool,\n        \"default\": False,\n        \"description\": \"Whether to confirm the action.\",\n    },\n    \"count\": {\n        \"type\": int,\n        \"default\": 1,\n        \"description\": \"Number of times to repeat the action.\",\n        \"validation\": lambda x: x > 0 or \"Count must be a positive integer.\"\n    },\n    \"path\": {\n        \"type\": Path,\n        \"description\": \"Path to your file.\",\n        \"required\": True\n    },\n    \"options\": {\n        \"type\": str,\n        \"choices\": [\"optA\", \"optB\", \"optC\", \"optD\"],\n        \"description\": \"Select one or more options.\",\n        \"multiple\": True\n    },\n    \"custom\": {\n        \"type\": MyCustomClass,\n        \"description\": \"An instance of MyCustomClass.\",\n    },\n    \"environment_var\": {\n        \"type\": str,\n        \"default\": \"${MY_ENV_VAR}\",\n        \"description\": \"An environment variable value.\",\n    }\n}\n```\n\n##### `run(context)`\n\nThe `run(context)` function serves as the main entry point for your script. It receives a `Context` object, which provides convenient access to everything your script needs:\n\n- **Parameter values:** Retrieve user-supplied or defaulted parameters via `context.params`.\n- **Environment variables:** Access environment variables loaded from `.env` or the system using `context.env`.\n- **Dynamic parameter prompting:** Use `context.add_params()` to request additional input from the user at runtime (available only in interactive mode).\n- **Script composition:** Invoke other Giorgio scripts programmatically with `context.call_script()`.\n\nThis design enables your scripts to be both flexible and composable, supporting interactive workflows and automation scenarios with minimal boilerplate.\n\n```python\ndef run(context):\n    try:\n        # Get the path parameter\n        path: Path = context.params[\"path\"]\n\n        # Grab an environment variable (or fall back to a default)\n        username = context.env.get(\"USER\", \"mysterious_automator\")\n        print(f\"\ud83d\udc4b Hello, {username}! Let's see what's in {path}...\")\n\n        # Find all .txt files and prompt the user to pick their favorite\n        context.add_params({\n            \"favorite_file\": {\n                \"type\": Path,\n                \"description\": \"Which text file deserves your attention today?\",\n                \"choices\": txt_files,\n                \"required\": True\n            }\n        })\n        favorite = context.params[\"favorite_file\"]\n        print(f\"\ud83c\udf89 You picked: {favorite.name}\")\n\n        # Call another script to celebrate\n        context.call_script(\"celebrate_file\", {\"file\": favorite})\n\n    except GiorgioCancellationError:\n        print(\"\ud83d\udea8 Script execution cancelled! Maybe next time...\")\n```\n\n### 3. Run Scripts\n\n#### Non-interactive (for automation):\n\nTo execute your script non-interactively, you can use the `run` command followed by the script name and any required parameters:\n\n```bash\ngiorgio run my_script \\\n  --param input_file=./data.txt \\\n  --param count=5\n```\n\nAll required parameters must be provided when running scripts non-interactively. The command supports boolean flags, lists, and allows you to use environment variable placeholders (such as `${VAR}`) as default values for parameters.\n\n#### Interactive (exploratory):\n\nFor an interactive experience, start Giorgio in interactive mode:\n\n```bash\ngiorgio start [--ui RENDERER]\n```\n\nWhen running in interactive mode, Giorgio presents a menu of available scripts and guides you through each required parameter, providing validation, default values, and helpful descriptions. Output from your script is streamed live to your terminal, and you can safely abort execution with Ctrl+C.\n\nGiorgio supports **pluggable UI renderers** for interactive mode. By default, the CLI renderer is used, but you can specify another renderer with the `--ui` option if additional renderers are installed. To see available renderers, run:\n\n```bash\ngiorgio start --help\n```\n\nTo add new UI renderers (such as a GUI or web interface), install a compatible plugin that registers itself under the `giorgio.ui_renderers` entry point. Once installed, the new renderer will be available for selection via the `--ui` flag.\n\nThis extensibility allows you to tailor the interactive experience to your workflow, whether you prefer a classic terminal UI or a custom interface.\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.8\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.4.0",
    "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": "ca0086e7a8f365579d748bccb49e7d1937ee702f756100cca20e7fc35569776d",
                "md5": "810a6a30809b505d31c23a4579d1d85c",
                "sha256": "e209557bde80c250ae69093af05ce00bfa18c69278441ffdba0c4e7b1c2164a3"
            },
            "downloads": -1,
            "filename": "giorgio-1.4.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "810a6a30809b505d31c23a4579d1d85c",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4.0,>=3.8",
            "size": 23749,
            "upload_time": "2025-07-11T08:50:06",
            "upload_time_iso_8601": "2025-07-11T08:50:06.113673Z",
            "url": "https://files.pythonhosted.org/packages/ca/00/86e7a8f365579d748bccb49e7d1937ee702f756100cca20e7fc35569776d/giorgio-1.4.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "b45847f7eed6a58633fe5148928897091176935cd80bd8f1f5af7d64d78d8f96",
                "md5": "a4486c83b558cefb315f10b61129885a",
                "sha256": "a0e26daf0356798e1f0c7bccd4975925e939a735af02a2d8bf6c5d30ca8b5477"
            },
            "downloads": -1,
            "filename": "giorgio-1.4.0.tar.gz",
            "has_sig": false,
            "md5_digest": "a4486c83b558cefb315f10b61129885a",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0,>=3.8",
            "size": 33875,
            "upload_time": "2025-07-11T08:50:07",
            "upload_time_iso_8601": "2025-07-11T08:50:07.376840Z",
            "url": "https://files.pythonhosted.org/packages/b4/58/47f7eed6a58633fe5148928897091176935cd80bd8f1f5af7d64d78d8f96/giorgio-1.4.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-11 08:50:07",
    "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: 0.47323s