Metadata-Version: 2.4
Name: genro-bag
Version: 0.13.2
Summary: Modernized bag system for the Genropy framework - hierarchical data container with XML serialization
Project-URL: Homepage, https://github.com/genropy/genro-bag
Project-URL: Documentation, https://genro-bag.readthedocs.io
Project-URL: Repository, https://github.com/genropy/genro-bag
Project-URL: Issues, https://github.com/genropy/genro-bag/issues
Author: Genropy Team
License-Expression: Apache-2.0
License-File: LICENSE
License-File: NOTICE
Keywords: bag,data-container,genro,genropy,hierarchical-data,xml-serialization
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
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 :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: genro-toolbox>=0.6.1
Requires-Dist: genro-tytx>=0.1.0
Provides-Extra: all
Requires-Dist: httpx>=0.27; extra == 'all'
Requires-Dist: httpx>=0.27.0; extra == 'all'
Requires-Dist: msgpack>=1.0; extra == 'all'
Requires-Dist: mypy>=1.0; extra == 'all'
Requires-Dist: myst-parser>=4.0.0; extra == 'all'
Requires-Dist: orjson>=3.9; extra == 'all'
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'all'
Requires-Dist: pytest-cov>=4.0; extra == 'all'
Requires-Dist: pytest>=7.0; extra == 'all'
Requires-Dist: ruff>=0.1.0; extra == 'all'
Requires-Dist: sphinx-autodoc-typehints>=3.0.0; extra == 'all'
Requires-Dist: sphinx-rtd-theme>=3.0.0; extra == 'all'
Requires-Dist: sphinx>=8.0.0; extra == 'all'
Requires-Dist: sphinxcontrib-mermaid>=1.0.0; extra == 'all'
Requires-Dist: xmlschema>=3.0; extra == 'all'
Provides-Extra: contrib-resolvers
Requires-Dist: httpx>=0.27; extra == 'contrib-resolvers'
Provides-Extra: contrib-resolvers-system
Requires-Dist: httpx>=0.27; extra == 'contrib-resolvers-system'
Requires-Dist: psutil; extra == 'contrib-resolvers-system'
Provides-Extra: dev
Requires-Dist: httpx>=0.27.0; extra == 'dev'
Requires-Dist: msgpack>=1.0; extra == 'dev'
Requires-Dist: mypy>=1.0; extra == 'dev'
Requires-Dist: orjson>=3.9; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: ruff>=0.1.0; extra == 'dev'
Provides-Extra: docs
Requires-Dist: myst-parser>=4.0.0; extra == 'docs'
Requires-Dist: sphinx-autodoc-typehints>=3.0.0; extra == 'docs'
Requires-Dist: sphinx-rtd-theme>=3.0.0; extra == 'docs'
Requires-Dist: sphinx>=8.0.0; extra == 'docs'
Requires-Dist: sphinxcontrib-mermaid>=1.0.0; extra == 'docs'
Provides-Extra: xsd-validate
Requires-Dist: xmlschema>=3.0; extra == 'xsd-validate'
Description-Content-Type: text/markdown

# genro-bag

[![PyPI version](https://img.shields.io/pypi/v/genro-bag)](https://pypi.org/project/genro-bag/)
[![Tests](https://github.com/genropy/genro-bag/actions/workflows/tests.yml/badge.svg)](https://github.com/genropy/genro-bag/actions/workflows/tests.yml)
[![codecov](https://codecov.io/gh/genropy/genro-bag/branch/main/graph/badge.svg)](https://codecov.io/gh/genropy/genro-bag)
[![Documentation](https://readthedocs.org/projects/genro-bag/badge/?version=latest)](https://genro-bag.readthedocs.io/)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)

## An Intermediate Representation for Structured Data

A **Bag** is an intermediate representation (IR) for hierarchical data in Python.

### What is an Intermediate Representation?

In compiler design, an IR is a data structure that sits between source code and machine code. It captures the essential structure while abstracting away format-specific details, making it easier to analyze, transform, and generate output.

The same principle applies to data: configuration files, API responses, documents, and UI structures all share a common shape—**named things containing values, organized hierarchically, with metadata attached**—but we typically scatter this across dictionaries, classes, JSON, XML, and database rows.

A Bag provides a **canonical representation** for this common pattern:

```mermaid
flowchart LR
    subgraph Sources
        JSON[JSON file]
        XML[XML file]
        API[API response]
        DB[Database]
        Input[User input]
    end

    subgraph BAG[" "]
        Tree["Unified tree<br/>of named nodes"]
    end

    subgraph Outputs
        HTML[HTML]
        XMLout[XML]
        DBout[Database]
        JSONout[JSON]
        UI[UI]
    end

    JSON --> Tree
    XML --> Tree
    API --> Tree
    DB --> Tree
    Input --> Tree

    Tree --> HTML
    Tree --> XMLout
    Tree --> DBout
    Tree --> JSONout
    Tree --> UI
```

### Why an IR?

**Decoupling**: Your application logic works with one structure, regardless of input/output formats. Change your data source from XML to JSON? Your code doesn't change.

**Uniformity**: One access pattern (`bag['path.to.value']`), one way to attach metadata, one subscription model—instead of learning different APIs for each library.

**Transformation**: Operate on the structure itself: walk the tree, filter nodes, transform values, validate structure—without knowing if it came from a file, an API, or a database.

**Round-tripping**: Serialize to XML, JSON, or MessagePack and back, preserving types, attributes, and structure—including lazy-loaded values (resolvers).

### The Core Model

Every node in a Bag has:

| Component | Purpose |
|-----------|---------|
| **Label** | The node's name (key in the hierarchy) |
| **Value** | The data it holds (any Python value, or another Bag) |
| **Attributes** | Metadata attached to the node |
| **Tag** | Optional semantic type (like XML elements) |

Access is path-based: `bag['config.database.host']` navigates the hierarchy using dot notation.

### Progressive Capability

Bag provides four layers—use only what you need:

| Layer | Purpose | Use When |
|-------|---------|----------|
| **Core Bag** | Paths, values, attributes, serialization | Always |
| **Resolvers** | Lazy-loaded, computed values | API calls, DB queries, expensive computations |
| **Subscriptions** | React to changes | Validation, logging, sync, computed properties |

## Interactive Notebooks

Try genro-bag directly in your browser with Google Colab:

| Notebook | Topics |
|----------|--------|
| [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/genropy/genro-bag/blob/main/notebooks/01-core-bag.ipynb) | **Core Bag** — Paths, values, attributes, serialization |
| [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/genropy/genro-bag/blob/main/notebooks/02-resolvers.ipynb) | **Resolvers** — Lazy loading, caching, custom resolvers |
| [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/genropy/genro-bag/blob/main/notebooks/03-subscriptions.ipynb) | **Subscriptions** — Events, validation, computed properties |

## Install

```bash
pip install genro-bag
```

## Documentation

| Resource | Description |
|----------|-------------|
| [**Full Documentation**](https://genro-bag.readthedocs.io/) | Complete guide with examples |
| [**Why Bag?**](https://genro-bag.readthedocs.io/en/latest/reference/why-bag.html) | Detailed comparison with alternatives |
| [**Getting Started**](https://genro-bag.readthedocs.io/en/latest/getting-started.html) | Learn the core concepts |

### In This Repository

| Directory | Description |
|-----------|-------------|
| [`src/genro_bag/`](src/genro_bag/) | Core implementation |
| [`src/genro_bag/resolvers/`](src/genro_bag/resolvers/) | Built-in resolvers (URL, Directory, OpenAPI) |
| [`examples/`](examples/) | Usage examples |
| [`tests/`](tests/) | Test suite (1500+ tests) |
| [`docs/`](docs/) | Sphinx documentation source |

## Development

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

## License

Apache License 2.0 — see [LICENSE](LICENSE) for details.

Copyright 2025 Softwell S.r.l. — Genropy Team
