Metadata-Version: 2.4
Name: graph-api-python
Version: 0.2.0
Summary: A fluent graph query library for Python with ElementStore and graph operations
Project-URL: Homepage, https://github.com/damylen/graph-api-python
Project-URL: Repository, https://github.com/damylen/graph-api-python
Project-URL: Documentation, https://github.com/damylen/graph-api-python#readme
Project-URL: Issues, https://github.com/damylen/graph-api-python/issues
Author-email: damylen <damylen@users.noreply.github.com>
License: MIT
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.8
Requires-Dist: pydantic>=2.0.0
Provides-Extra: all
Requires-Dist: bandit[toml]>=1.7.0; extra == 'all'
Requires-Dist: black>=23.0; extra == 'all'
Requires-Dist: build>=1.0; extra == 'all'
Requires-Dist: coverage[toml]>=7.0; extra == 'all'
Requires-Dist: isort>=5.12; extra == 'all'
Requires-Dist: mypy>=1.0; extra == 'all'
Requires-Dist: pip-audit>=2.0.0; extra == 'all'
Requires-Dist: pre-commit>=3.0; extra == 'all'
Requires-Dist: pytest-asyncio>=0.21.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: safety>=2.0.0; extra == 'all'
Requires-Dist: twine>=4.0; extra == 'all'
Provides-Extra: dev
Requires-Dist: bandit[toml]>=1.7.0; extra == 'dev'
Requires-Dist: black>=23.0; extra == 'dev'
Requires-Dist: build>=1.0; extra == 'dev'
Requires-Dist: coverage[toml]>=7.0; extra == 'dev'
Requires-Dist: isort>=5.12; extra == 'dev'
Requires-Dist: mypy>=1.0; extra == 'dev'
Requires-Dist: pip-audit>=2.0.0; extra == 'dev'
Requires-Dist: pre-commit>=3.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.21.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'
Requires-Dist: safety>=2.0.0; extra == 'dev'
Requires-Dist: twine>=4.0; extra == 'dev'
Provides-Extra: lint
Requires-Dist: bandit[toml]>=1.7.0; extra == 'lint'
Requires-Dist: black>=23.0; extra == 'lint'
Requires-Dist: isort>=5.12; extra == 'lint'
Requires-Dist: mypy>=1.0; extra == 'lint'
Requires-Dist: pip-audit>=2.0.0; extra == 'lint'
Requires-Dist: ruff>=0.1.0; extra == 'lint'
Requires-Dist: safety>=2.0.0; extra == 'lint'
Provides-Extra: test
Requires-Dist: coverage[toml]>=7.0; extra == 'test'
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'test'
Requires-Dist: pytest-cov>=4.0; extra == 'test'
Requires-Dist: pytest>=7.0; extra == 'test'
Description-Content-Type: text/markdown

# Graph Elements Python Library

A Python library for graph-based data structures and queries, providing TypeScript-equivalent functionality for managing BaseElement, Node, Edge, MetaNode, and ElementStore classes with a powerful fluent GraphQuery API.

## Features

- 🧩 **Complete Graph Elements**: BaseElement, Node, Edge, MetaNode classes with full TypeScript parity
- 🔍 **Powerful Query API**: Fluent GraphQuery interface with comprehensive filtering operators
- � **Clean API**: Simple `addNode()`, `createNode()`, `addEdge()` methods with `Props` class
- 🔗 **Shorter Query Syntax**: `classId()`, `where()`, `gte()`, `order_by()`, `first()` aliases
- �🗄️ **Flexible Storage**: ElementStore with pluggable storage backends (memory, custom implementations)
- 📊 **Rich Filtering**: Support for EQ, GT, LT, GTE, LTE, BETWEEN, CONTAINS, STARTS_WITH, ENDS_WITH, REGEX, IN operators
- 🔄 **Method Chaining**: Intuitive fluent API for complex query composition
- 📈 **Aggregation Functions**: count, sum, mean/avg, median, min, max operations
- 🎯 **Type Safe**: Full typing support with TypeScript-equivalent interfaces
- ⚡ **Async Support**: Async versions of node and edge creation methods
- ✅ **Well Tested**: Comprehensive test suite with 297 test cases

## Installation

### For End Users

```bash
# Install from PyPI (recommended)
pip install graph-api-python

# Or install from GitHub (latest development version)
pip install git+https://github.com/damylen/graph-api-python.git@main

# Install specific version from GitHub
pip install git+https://github.com/damylen/graph-api-python.git@v0.1.0
```

### For Development

This project uses [uv](https://docs.astral.sh/uv/) for fast, reliable Python package management.

```bash
# Install uv
curl -LsSf https://astral.sh/uv/install.sh | sh

# Clone and set up the project
git clone <repository-url>
cd graph-api
uv sync
```

## Quick Start

```python
from graph_api import GraphQuery, ElementStore, Props

# Create an element store
store = ElementStore()

# Add nodes using the clean API
alice = store.addNode('person', name="Alice", age=30, tags=["developer", "senior"])
bob = store.addNode('person', name="Bob", age=28, tags=["designer"])

# Or create with Props object
props = Props(name="Carol", age=32, department="Engineering")
carol = store.addNode('person', props)

# Create edges between nodes
friendship = store.addEdge('friendship', alice, bob, strength=0.9, type="close_friends")

# Create queries with intuitive syntax
query = GraphQuery(store)

# Basic filtering
people = query.classId('person').r()

# Advanced filtering with method chaining
senior_devs = (query
    .classId('person')
    .gte('age', 25)
    .contains('tags', 'senior')
    .r())

# Aggregations
total_people = query.classId('person').count()
avg_age = query.classId('person').avg('age')

# Sorting and limiting
youngest = (query
    .classId('person')
    .order_by('age', 'asc')
    .first(5)
    .r())
```

## API Usage

The library provides a clean, intuitive API for graph operations:

### Node Operations

```python
from graph_api import ElementStore, Props

store = ElementStore()

# Add nodes with keyword arguments
person = store.addNode('person', name="John", age=30, city="Boston")

# Add nodes with Props object
props = Props(name="Alice", age=28, job="Engineer")
alice = store.addNode('person', props)

# Create nodes without adding to store
node = store.createNode('person', name="Bob", age=25)
# Later add to store
store.addNode(node)

# Async versions available
async def add_user():
    user = await store.addNodeAsync('user', name="Async User", active=True)
    return user
```

### Edge Operations

```python
# Create relationships between nodes
alice = store.addNode('person', name="Alice")
bob = store.addNode('person', name="Bob")

# Add edge with properties
friendship = store.addEdge('friendship', alice, bob, 
                          strength=0.9, type="close_friends")

# Create edge without adding to store
edge = store.createEdge('relationship', alice, bob, 
                       Props(type="colleague", department="Engineering"))

# Async edge creation
async def create_relationship():
    rel = await store.addEdgeAsync('follows', alice, bob, since="2023")
    return rel
```

### Props Class

The `Props` class provides a simple way to define element properties:

```python
from graph_api import Props

# Create props with keyword arguments
props = Props(name="Alice", age=30, job="Engineer")

# Props behaves like a dictionary
props['department'] = "Engineering"
assert props['name'] == "Alice"
assert 'age' in props
```



## Query Methods

### Filtering Methods

- `classId(class_id)`: Filter by element class ID
- `where(key, operator, value)`: Filter by property with operator 
- `where(key, value)`: Filter by property equality (shorthand)
- `prop(key, value)`: Alias for property equality
- `gt(key, value)`, `lt(key, value)`, `gte(key, value)`, `lte(key, value)`: Comparison operators
- `contains(key, value)`: Check if property contains value
- `startsWith(key, value)`, `endsWith(key, value)`: String matching

### Sorting and Limiting

- `order_by(property, direction)`: Sort by property ('asc' or 'desc')
- `first(n)`: Limit to first N results
- `last(n)`: Limit to last N results

### Aggregation Methods

- `count()`: Count results
- `sum(property)`: Sum numeric property
- `avg(property)`: Average of numeric property
- `median(property)`: Median of numeric property
- `min(property)`: Minimum of numeric property
- `max(property)`: Maximum of numeric property

### Example Usage

```python
# Chain methods for complex queries
young_engineers = (query
    .classId('person')
    .where('department', 'Engineering')
    .lt('age', 35)
    .order_by('age', 'desc')
    .first(10)
    .r())

# Use comparison operators
seniors = query.classId('person').gte('age', 30).r()

# Aggregations
avg_age = query.classId('person').avg('age')
total_people = query.classId('person').count()
```

## Development

This project uses [uv](https://docs.astral.sh/uv/) for dependency management and development workflows.

### Prerequisites

- Python 3.12+
- [uv](https://docs.astral.sh/uv/)

### Setup

```bash
# Install uv if you haven't already
curl -LsSf https://astral.sh/uv/install.sh | sh

# Clone the repository
git clone <repository-url>
cd graph-api

# Create virtual environment and install dependencies
uv sync

# Install in development mode
uv pip install -e .
```

### Running Tests

```bash
# Run all tests
uv run pytest tests/ -v

# Run tests with coverage
uv run pytest tests/ -v --cov=graph_api --cov-report=html

# Run specific test file
uv run pytest tests/test_graph_query.py -v
```

### Code Quality

```bash
# Run linting
uv run ruff check .

# Format code
uv run black .

# Sort imports
uv run isort .

# Type checking
uv run mypy graph_api/

# All quality checks
uv run ruff check . && uv run black --check . && uv run isort --check-only . && uv run mypy graph_api/
```

### Adding Dependencies

```bash
# Add runtime dependency
uv add requests

# Add development dependency
uv add --dev pytest-mock

# Update dependencies
uv lock --upgrade
```

### Using Makefile (Optional)

For convenience, common development tasks are available via Makefile:

```bash
# Set up development environment
make dev

# Run all quality checks and tests
make qa

# Run tests with coverage
make test

# Format code and fix linting
make lint-fix

# Build package
make build

# See all available commands
make help
```

### Test Coverage

- ✅ 297 tests passing
- ✅ All filtering operators tested
- ✅ Method chaining validated
- ✅ Edge cases covered
- ✅ Aggregation functions verified
- ✅ Clean API methods tested
- ✅ Async operations validated

## License

MIT License

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.