rh


Namerh JSON
Version 0.0.9 PyPI version JSON
download
home_pagehttps://github.com/i2mint/rh
SummaryReactive Html Framework - Transform variable relationships into interactive web apps
upload_time2025-08-30 15:03:43
maintainerNone
docs_urlNone
authorOtoSense
requires_python>=3.8
licensemit
keywords reactive html web-apps interactive forms javascript mesh reactive-programming data-flow rjsf real-time web-framework ui-generation declarative computational-graph
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # RH - Reactive Html Framework

Transform variable relationships into interactive web applications with real-time updates.

## Quick Start

```python
from rh import MeshBuilder

# Define relationships between variables
mesh_spec = {
    "temp_fahrenheit": ["temp_celsius"],
    "temp_kelvin": ["temp_celsius"],
}

# Define how to compute each relationship
functions_spec = {
    "temp_fahrenheit": "return temp_celsius * 9/5 + 32;",
    "temp_kelvin": "return temp_celsius + 273.15;",
}

# Set initial values
initial_values = {
    "temp_celsius": 20.0
}

# Create and build the app
builder = MeshBuilder(mesh_spec, functions_spec, initial_values)
app_path = builder.build_app(title="Temperature Converter")

# Serve it locally
builder.serve(port=8080)
```

## Features

- **Bidirectional Dependencies**: Variables can depend on each other cyclically
- **Real-time Updates**: Changes propagate instantly through the mesh
- **Convention over Configuration**: Smart defaults based on variable names
- **Type Inference**: Automatic UI widget selection from initial values
- **Zero External Dependencies**: Works with Python stdlib only

## UI Conventions

Variable names automatically determine UI behavior:

```python
initial_values = {
    "slider_opacity": 50,        # → Range slider (0-100)
    "readonly_result": 0,        # → Read-only display
    "hidden_internal": 10,       # → Hidden field
    "color_theme": "#ff0000",    # → Color picker
    "date_created": "2023-01-01" # → Date input
}
```

## Advanced Example

```python
# Physics calculator with custom field overrides
mesh_spec = {
    "kinetic_energy": ["mass", "velocity"],
    "momentum": ["mass", "velocity"],
    "total_energy": ["kinetic_energy", "potential_energy"]
}

functions_spec = {
    "kinetic_energy": "return 0.5 * mass * velocity * velocity;",
    "momentum": "return mass * velocity;",
    "total_energy": "return kinetic_energy + potential_energy;"
}

field_overrides = {
    "mass": {
        "title": "Mass (kg)",
        "minimum": 0.1,
        "maximum": 1000,
        "ui:help": "Object mass in kilograms"
    }
}

builder = MeshBuilder(mesh_spec, functions_spec, 
                     initial_values={"mass": 10, "velocity": 5, "potential_energy": 100},
                     field_overrides=field_overrides)
```

## Testing

Run the test suite:

```bash
# Run pytest discovery from the project root (recommended)
python -m pytest
```

## Demo

Try the examples:

```bash
python demo.py      # Multiple example apps
python example.py   # Simple temperature converter with server
python persistent_apps_example.py  # Shows app directory management
```

## App Directory Management

RH automatically manages app storage for persistent applications:

### Default Behavior

```python
builder = MeshBuilder(mesh_spec, functions_spec, initial_values)

# App name inferred from title, stored in RH_APP_FOLDER
app_path = builder.build_app(title="Temperature Converter")
# Creates: ~/.rh/apps/temperature_converter/index.html

# Explicit app name
app_path = builder.build_app(title="My App", app_name="custom_name")
# Creates: ~/.rh/apps/custom_name/index.html
```

### Directory Configuration

```python
from rh.util import RH_APP_FOLDER, get_app_directory

# Check current app folder location
print(f"Apps stored in: {RH_APP_FOLDER}")

# Get path for specific app
app_dir = get_app_directory("my_calculator")
```

### Environment Variables

Control where RH stores apps by setting environment variables:

```bash
# Custom app folder location
export RH_APP_FOLDER="/path/to/my/apps"

# Custom local data folder (apps will be in $RH_LOCAL_DATA_FOLDER/apps)
export RH_LOCAL_DATA_FOLDER="/path/to/my/data"
```

### Manual Directory Control

For full control over output location:

```python
builder = MeshBuilder(mesh_spec, functions_spec, initial_values)
builder.output_dir = "/path/to/specific/location"
app_path = builder.build_app(title="My App")
```

## Design & Philosophy

This section communicates the design principles and architectural decisions that guide the development of RH, helping both users understand the framework's approach and contributors align with the project's vision. **Contributors are welcome!!!**

### Core Design Principles

**🧩 Declarative over Imperative**
- Users describe *what* relationships exist between variables, not *how* to update the UI
- The framework handles the complex orchestration of updates, event handling, and DOM manipulation
- Mental model: "I have variables that relate to each other" → "I get a working interactive app"

**🔄 Convention over Configuration**
- Smart defaults based on naming patterns (`slider_*`, `readonly_*`, `hidden_*`)
- Type inference from initial values (float → number input, bool → checkbox)
- Zero-config working apps, with escape hatches for customization when needed

**⚡ Functional Programming & Immutability**
- Pure functions with no side effects in core logic
- Immutable configuration objects generated once and used everywhere
- Predictable behavior through referential transparency
- Data transformations rather than object mutations

### Architectural Decisions

**📐 Clean Architecture**
```
┌─────────────────┐
│   MeshBuilder   │  ← Facade/Interface Layer
│    (Facade)     │
├─────────────────┤
│ Generators      │  ← Application Logic
│ • HTML          │
│ • RJSF Schema   │
├─────────────────┤
│ Core Logic      │  ← Business Logic
│ • Type Inference│
│ • Propagation   │
│ • Validation    │
├─────────────────┤
│ Infrastructure  │  ← Framework/Tools
│ • HTTP Server   │
│ • File I/O      │
│ • Templates     │
└─────────────────┘
```

**🔧 Separation of Concerns**
- **Specification Layer**: Parse and validate user input (mesh specs, functions)
- **Configuration Layer**: Transform specs into explicit, normalized config
- **Generation Layer**: Create output artifacts (HTML, JS, schemas) from config
- **Runtime Layer**: Serve applications and handle deployment

**🎯 Single Source of Truth (SSOT)**
- The `generate_config()` method produces the canonical representation
- All downstream components (HTML generator, RJSF schemas, JS functions) consume only this config
- No scattered state or multiple sources of truth

**🔌 Dependency Injection & Plugin Architecture**
- Pluggable components for different output formats
- Registry pattern for optional tool detection (Jinja2, esbuild, etc.)
- Interface-based design allowing custom generators and processors

### Development Philosophy

**📚 Zero Dependencies by Design**
- Core functionality works with Python stdlib only
- Optional enhancements auto-detected and registered
- Reduces deployment complexity and increases reliability

**🧪 Test-Driven Development**
- Tests written first to clarify requirements and edge cases
- Comprehensive test coverage (24+ tests) ensuring behavioral correctness
- Integration tests verify end-to-end functionality

**📖 Documentation as Code**
- README examples are tested as part of the test suite
- Docstrings include type hints and behavioral descriptions
- Self-documenting code through clear naming and structure

**🌱 Incremental Complexity**
- Simple use cases work with minimal code
- Advanced features available through progressive disclosure
- Each abstraction level serves a clear purpose

### Contributor Guidelines

**🤝 What We Welcome**
- **New Generators**: Support for other UI frameworks (Vue, Angular, Svelte)
- **Input Parsers**: YAML/TOML mesh specs, Excel formula parsing, natural language
- **Enhanced Conventions**: More naming patterns, automatic grouping, layout hints
- **Performance Optimizations**: Faster propagation algorithms, caching strategies
- **Developer Experience**: Better error messages, debugging tools, IDE integration

**🎨 Code Style Expectations**
- **Functional first**: Prefer pure functions and data transformations
- **Type hints**: All public APIs should be fully annotated
- **Docstrings**: Include behavior descriptions and simple doctests where applicable
- **Modular design**: Single responsibility principle, composable components
- **Immutable data**: Avoid mutation, prefer transformation and copying

**🏗️ Architectural Consistency**
- New features should extend existing patterns rather than introduce new paradigms
- Maintain the declarative user interface - complexity hidden behind simple APIs
- Follow the SSOT principle - all generators work from the same configuration
- Preserve zero-dependency core with optional enhancements

**🔍 Testing Philosophy**
- Write tests first to clarify the expected behavior
- Test both happy paths and edge cases
- Include integration tests for user-facing workflows
- Ensure examples in documentation actually work

This framework embodies the principle that **complexity should be in the implementation, not the interface**. Users describe simple relationships; the framework handles the complexity of turning those into rich, interactive applications.

## License

MIT License - see LICENSE file for details.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/i2mint/rh",
    "name": "rh",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "reactive, html, web-apps, interactive, forms, javascript, mesh, reactive-programming, data-flow, rjsf, real-time, web-framework, ui-generation, declarative, computational-graph",
    "author": "OtoSense",
    "author_email": "thor@otosense.ai",
    "download_url": "https://files.pythonhosted.org/packages/85/1b/ba4b29d7c58ea2ff4a54e151d47d7166d9623b439368a8d676d0c6436ce8/rh-0.0.9.tar.gz",
    "platform": "any",
    "description": "# RH - Reactive Html Framework\n\nTransform variable relationships into interactive web applications with real-time updates.\n\n## Quick Start\n\n```python\nfrom rh import MeshBuilder\n\n# Define relationships between variables\nmesh_spec = {\n    \"temp_fahrenheit\": [\"temp_celsius\"],\n    \"temp_kelvin\": [\"temp_celsius\"],\n}\n\n# Define how to compute each relationship\nfunctions_spec = {\n    \"temp_fahrenheit\": \"return temp_celsius * 9/5 + 32;\",\n    \"temp_kelvin\": \"return temp_celsius + 273.15;\",\n}\n\n# Set initial values\ninitial_values = {\n    \"temp_celsius\": 20.0\n}\n\n# Create and build the app\nbuilder = MeshBuilder(mesh_spec, functions_spec, initial_values)\napp_path = builder.build_app(title=\"Temperature Converter\")\n\n# Serve it locally\nbuilder.serve(port=8080)\n```\n\n## Features\n\n- **Bidirectional Dependencies**: Variables can depend on each other cyclically\n- **Real-time Updates**: Changes propagate instantly through the mesh\n- **Convention over Configuration**: Smart defaults based on variable names\n- **Type Inference**: Automatic UI widget selection from initial values\n- **Zero External Dependencies**: Works with Python stdlib only\n\n## UI Conventions\n\nVariable names automatically determine UI behavior:\n\n```python\ninitial_values = {\n    \"slider_opacity\": 50,        # \u2192 Range slider (0-100)\n    \"readonly_result\": 0,        # \u2192 Read-only display\n    \"hidden_internal\": 10,       # \u2192 Hidden field\n    \"color_theme\": \"#ff0000\",    # \u2192 Color picker\n    \"date_created\": \"2023-01-01\" # \u2192 Date input\n}\n```\n\n## Advanced Example\n\n```python\n# Physics calculator with custom field overrides\nmesh_spec = {\n    \"kinetic_energy\": [\"mass\", \"velocity\"],\n    \"momentum\": [\"mass\", \"velocity\"],\n    \"total_energy\": [\"kinetic_energy\", \"potential_energy\"]\n}\n\nfunctions_spec = {\n    \"kinetic_energy\": \"return 0.5 * mass * velocity * velocity;\",\n    \"momentum\": \"return mass * velocity;\",\n    \"total_energy\": \"return kinetic_energy + potential_energy;\"\n}\n\nfield_overrides = {\n    \"mass\": {\n        \"title\": \"Mass (kg)\",\n        \"minimum\": 0.1,\n        \"maximum\": 1000,\n        \"ui:help\": \"Object mass in kilograms\"\n    }\n}\n\nbuilder = MeshBuilder(mesh_spec, functions_spec, \n                     initial_values={\"mass\": 10, \"velocity\": 5, \"potential_energy\": 100},\n                     field_overrides=field_overrides)\n```\n\n## Testing\n\nRun the test suite:\n\n```bash\n# Run pytest discovery from the project root (recommended)\npython -m pytest\n```\n\n## Demo\n\nTry the examples:\n\n```bash\npython demo.py      # Multiple example apps\npython example.py   # Simple temperature converter with server\npython persistent_apps_example.py  # Shows app directory management\n```\n\n## App Directory Management\n\nRH automatically manages app storage for persistent applications:\n\n### Default Behavior\n\n```python\nbuilder = MeshBuilder(mesh_spec, functions_spec, initial_values)\n\n# App name inferred from title, stored in RH_APP_FOLDER\napp_path = builder.build_app(title=\"Temperature Converter\")\n# Creates: ~/.rh/apps/temperature_converter/index.html\n\n# Explicit app name\napp_path = builder.build_app(title=\"My App\", app_name=\"custom_name\")\n# Creates: ~/.rh/apps/custom_name/index.html\n```\n\n### Directory Configuration\n\n```python\nfrom rh.util import RH_APP_FOLDER, get_app_directory\n\n# Check current app folder location\nprint(f\"Apps stored in: {RH_APP_FOLDER}\")\n\n# Get path for specific app\napp_dir = get_app_directory(\"my_calculator\")\n```\n\n### Environment Variables\n\nControl where RH stores apps by setting environment variables:\n\n```bash\n# Custom app folder location\nexport RH_APP_FOLDER=\"/path/to/my/apps\"\n\n# Custom local data folder (apps will be in $RH_LOCAL_DATA_FOLDER/apps)\nexport RH_LOCAL_DATA_FOLDER=\"/path/to/my/data\"\n```\n\n### Manual Directory Control\n\nFor full control over output location:\n\n```python\nbuilder = MeshBuilder(mesh_spec, functions_spec, initial_values)\nbuilder.output_dir = \"/path/to/specific/location\"\napp_path = builder.build_app(title=\"My App\")\n```\n\n## Design & Philosophy\n\nThis section communicates the design principles and architectural decisions that guide the development of RH, helping both users understand the framework's approach and contributors align with the project's vision. **Contributors are welcome!!!**\n\n### Core Design Principles\n\n**\ud83e\udde9 Declarative over Imperative**\n- Users describe *what* relationships exist between variables, not *how* to update the UI\n- The framework handles the complex orchestration of updates, event handling, and DOM manipulation\n- Mental model: \"I have variables that relate to each other\" \u2192 \"I get a working interactive app\"\n\n**\ud83d\udd04 Convention over Configuration**\n- Smart defaults based on naming patterns (`slider_*`, `readonly_*`, `hidden_*`)\n- Type inference from initial values (float \u2192 number input, bool \u2192 checkbox)\n- Zero-config working apps, with escape hatches for customization when needed\n\n**\u26a1 Functional Programming & Immutability**\n- Pure functions with no side effects in core logic\n- Immutable configuration objects generated once and used everywhere\n- Predictable behavior through referential transparency\n- Data transformations rather than object mutations\n\n### Architectural Decisions\n\n**\ud83d\udcd0 Clean Architecture**\n```\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502   MeshBuilder   \u2502  \u2190 Facade/Interface Layer\n\u2502    (Facade)     \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Generators      \u2502  \u2190 Application Logic\n\u2502 \u2022 HTML          \u2502\n\u2502 \u2022 RJSF Schema   \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Core Logic      \u2502  \u2190 Business Logic\n\u2502 \u2022 Type Inference\u2502\n\u2502 \u2022 Propagation   \u2502\n\u2502 \u2022 Validation    \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Infrastructure  \u2502  \u2190 Framework/Tools\n\u2502 \u2022 HTTP Server   \u2502\n\u2502 \u2022 File I/O      \u2502\n\u2502 \u2022 Templates     \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n**\ud83d\udd27 Separation of Concerns**\n- **Specification Layer**: Parse and validate user input (mesh specs, functions)\n- **Configuration Layer**: Transform specs into explicit, normalized config\n- **Generation Layer**: Create output artifacts (HTML, JS, schemas) from config\n- **Runtime Layer**: Serve applications and handle deployment\n\n**\ud83c\udfaf Single Source of Truth (SSOT)**\n- The `generate_config()` method produces the canonical representation\n- All downstream components (HTML generator, RJSF schemas, JS functions) consume only this config\n- No scattered state or multiple sources of truth\n\n**\ud83d\udd0c Dependency Injection & Plugin Architecture**\n- Pluggable components for different output formats\n- Registry pattern for optional tool detection (Jinja2, esbuild, etc.)\n- Interface-based design allowing custom generators and processors\n\n### Development Philosophy\n\n**\ud83d\udcda Zero Dependencies by Design**\n- Core functionality works with Python stdlib only\n- Optional enhancements auto-detected and registered\n- Reduces deployment complexity and increases reliability\n\n**\ud83e\uddea Test-Driven Development**\n- Tests written first to clarify requirements and edge cases\n- Comprehensive test coverage (24+ tests) ensuring behavioral correctness\n- Integration tests verify end-to-end functionality\n\n**\ud83d\udcd6 Documentation as Code**\n- README examples are tested as part of the test suite\n- Docstrings include type hints and behavioral descriptions\n- Self-documenting code through clear naming and structure\n\n**\ud83c\udf31 Incremental Complexity**\n- Simple use cases work with minimal code\n- Advanced features available through progressive disclosure\n- Each abstraction level serves a clear purpose\n\n### Contributor Guidelines\n\n**\ud83e\udd1d What We Welcome**\n- **New Generators**: Support for other UI frameworks (Vue, Angular, Svelte)\n- **Input Parsers**: YAML/TOML mesh specs, Excel formula parsing, natural language\n- **Enhanced Conventions**: More naming patterns, automatic grouping, layout hints\n- **Performance Optimizations**: Faster propagation algorithms, caching strategies\n- **Developer Experience**: Better error messages, debugging tools, IDE integration\n\n**\ud83c\udfa8 Code Style Expectations**\n- **Functional first**: Prefer pure functions and data transformations\n- **Type hints**: All public APIs should be fully annotated\n- **Docstrings**: Include behavior descriptions and simple doctests where applicable\n- **Modular design**: Single responsibility principle, composable components\n- **Immutable data**: Avoid mutation, prefer transformation and copying\n\n**\ud83c\udfd7\ufe0f Architectural Consistency**\n- New features should extend existing patterns rather than introduce new paradigms\n- Maintain the declarative user interface - complexity hidden behind simple APIs\n- Follow the SSOT principle - all generators work from the same configuration\n- Preserve zero-dependency core with optional enhancements\n\n**\ud83d\udd0d Testing Philosophy**\n- Write tests first to clarify the expected behavior\n- Test both happy paths and edge cases\n- Include integration tests for user-facing workflows\n- Ensure examples in documentation actually work\n\nThis framework embodies the principle that **complexity should be in the implementation, not the interface**. Users describe simple relationships; the framework handles the complexity of turning those into rich, interactive applications.\n\n## License\n\nMIT License - see LICENSE file for details.\n",
    "bugtrack_url": null,
    "license": "mit",
    "summary": "Reactive Html Framework - Transform variable relationships into interactive web apps",
    "version": "0.0.9",
    "project_urls": {
        "Bug Reports": "https://github.com/i2mint/rh/issues",
        "Documentation": "https://github.com/i2mint/rh#readme",
        "Homepage": "https://github.com/i2mint/rh",
        "Source": "https://github.com/i2mint/rh"
    },
    "split_keywords": [
        "reactive",
        " html",
        " web-apps",
        " interactive",
        " forms",
        " javascript",
        " mesh",
        " reactive-programming",
        " data-flow",
        " rjsf",
        " real-time",
        " web-framework",
        " ui-generation",
        " declarative",
        " computational-graph"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "e5ed9f1b496def7dd17abbc8195d7a5da4b0f999dd26dbf399ff0c3534b860cf",
                "md5": "11741b0d7b89d991e178982bd3b41733",
                "sha256": "5bb2cd40efcb500045d1b07ae559abb1044a5dc13bdc958ca0e312b49e274706"
            },
            "downloads": -1,
            "filename": "rh-0.0.9-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "11741b0d7b89d991e178982bd3b41733",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 17839,
            "upload_time": "2025-08-30T15:03:42",
            "upload_time_iso_8601": "2025-08-30T15:03:42.504872Z",
            "url": "https://files.pythonhosted.org/packages/e5/ed/9f1b496def7dd17abbc8195d7a5da4b0f999dd26dbf399ff0c3534b860cf/rh-0.0.9-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "851bba4b29d7c58ea2ff4a54e151d47d7166d9623b439368a8d676d0c6436ce8",
                "md5": "0ce7d8ef45484ba0fff5ffb5dc843f0a",
                "sha256": "7965d38709c92f977c0eaee603c3fa465a75bc184407dc26e3af4a857fde32e5"
            },
            "downloads": -1,
            "filename": "rh-0.0.9.tar.gz",
            "has_sig": false,
            "md5_digest": "0ce7d8ef45484ba0fff5ffb5dc843f0a",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 20556,
            "upload_time": "2025-08-30T15:03:43",
            "upload_time_iso_8601": "2025-08-30T15:03:43.514030Z",
            "url": "https://files.pythonhosted.org/packages/85/1b/ba4b29d7c58ea2ff4a54e151d47d7166d9623b439368a8d676d0c6436ce8/rh-0.0.9.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-30 15:03:43",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "i2mint",
    "github_project": "rh",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "rh"
}
        
Elapsed time: 0.71162s