Metadata-Version: 2.1
Name: pyvrita
Version: 0.1.0
Summary: A Python web framework inspired by Sails.js and Laravel
Author-email: Suraj Patel <suraj@example.com>
Keywords: python,framework,web,orm,rest,activerecord
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: sqlalchemy>=2.0
Requires-Dist: starlette>=0.35
Requires-Dist: uvicorn[standard]>=0.27
Requires-Dist: click>=8.1
Requires-Dist: colorama>=0.4
Requires-Dist: python-dotenv>=1.0
Requires-Dist: alembic>=1.12
Requires-Dist: httpx>=0.25
Requires-Dist: redis>=5.0
Requires-Dist: psycopg2-binary>=2.9
Requires-Dist: jinja2>=3.1
Provides-Extra: dev
Requires-Dist: pytest>=7.4; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
Requires-Dist: black>=23.0; extra == "dev"
Requires-Dist: ruff>=0.1; extra == "dev"
Requires-Dist: mypy>=1.0; extra == "dev"

# PyVrita

A Python web framework inspired by Sails.js and Laravel, providing a full-featured toolkit for building scalable, production-ready web applications.

![Tests Passing](https://img.shields.io/badge/tests-38%2F38%20passing-brightgreen)
![Python](https://img.shields.io/badge/python-3.9+-blue)
![License](https://img.shields.io/badge/license-MIT-green)

## 🚀 Features

- **Active Record ORM** - Intuitive data access with automatic session management
- **High-Performance ASGI** - Modern async architecture for high concurrency
- **REST Blueprints** - Convention-based automatic routing
- **Policy Authorization** - Globally available authorization logic
- **Database Migrations** - Version control for your schema
- **Multiple Databases** - Per-model database binding and configuration
- **Code Generators** - Scaffold models, controllers, and more
- **Testing Framework** - Factories, fixtures, and test client
- **Auto-Discovery** - Automatic module loading and registration
- **Structured Logging** - JSON-formatted logs with context binding

## 📋 Table of Contents

### For Users
- [Getting Started](#getting-started) - Quick start guide
- [Documentation](#documentation) - Full user guide
- [Examples](#examples) - Example applications

### For Contributors
- [Development Setup](#development-setup) - Set up your environment
- [Architecture](#architecture) - Framework internals
- [Core Concepts](#core-concepts) - Design patterns
- [Testing](#testing) - Running tests
- [Contributing](#contributing) - How to contribute
- [Publishing](#publishing) - Distribution guide

## 📦 For Users

To get started building applications with PyVrita:

1. **Read [USER_GUIDE.md](USER_GUIDE.md)** - Complete user documentation including installation, setup, and tutorials
2. **Install from PyPI** - `pipx install pyvrita`
3. **Start building** - Follow the USER_GUIDE for step-by-step instructions

## 📚 Documentation

**For Users:** Read [USER_GUIDE.md](USER_GUIDE.md) for:
- Installation and setup
- Creating models and controllers
- Building REST APIs
- Database configuration
- Authentication & authorization
- Testing your application
- Deployment guidelines
- Common patterns and troubleshooting

**For Contributors:** Continue reading this README for:
- Framework architecture
- Core concepts and design patterns
- Development setup
- Testing framework code
- Publishing and distribution

## 💡 Examples

### Simple Blog Application

```python
# app/models/post.py
from pyvrita import Model, String, Text, Boolean

class Post(Model):
    __tablename__ = 'posts'
    __database__ = 'mysql'
    
    title = String(unique=True)
    content = Text()
    published = Boolean(default=False)

# app/controllers/posts_controller.py
from pyvrita import Controller

class PostsController(Controller):
    async def find(self):
        # Post is globally available (Sails.js style)
        return Post.where('published', True).get()
    
    async def find_one(self, id):
        return Post.find(id)
    
    async def create(self):
        data = await self.request.json()
        return Post.create(**data), 201
```

See [USER_GUIDE.md](USER_GUIDE.md#building-rest-apis) for more examples.

---

## 🏗️ Architecture

### Core Components

```
┌─────────────────────────────────────────────────────────┐
│                    PyVrita App                          │
├─────────────────────────────────────────────────────────┤
│  ASGI Core          │ Active Record ORM │ Policy Router │
├─────────────────────────────────────────────────────────┤
│     REST Layer       │   ORM Layer     │  Auth Layer    │
├─────────────────────────────────────────────────────────┤
│  Controllers         │ Models          │ Policies       │
│  Services           │ Migrations       │ Middleware     │
└─────────────────────────────────────────────────────────┘
```

### Directory Structure

```
pyvrita/
├── app/                    # Application core
│   ├── controllers/       # Controller abstractions
│   ├── middlewares/       # HTTP middlewares
│   └── http.py            # Request/Response abstractions
├── orm/                    # Active Record & ORM engine
│   ├── _base.py           # Model base class
│   └── _fields.py         # Field type definitions
├── rest/                   # REST routing engine
│   └── _router.py         # Blueprint discovery
├── policies/               # Authorization system
│   └── _base.py           # Policy base class
├── migrations/            # Database versioning
├── testing/               # Test toolkit & factories
├── logging/               # Structured logging system
└── __init__.py           # Public framework API
```

## 📚 Core Concepts

### Models (ORM Layer)

Models use a powerful Active Record pattern with support for relationships, eager loading, and cascades:

```python
from pyvrita import Model, String, Integer, ForeignKey, SoftDeleteMixin

class User(Model, SoftDeleteMixin):
    __tablename__ = 'users'
    
    name = String()
    email = String(unique=True)
    
    # Relationships
    posts = HasMany('Post', foreign_key='user_id')

class Post(Model):
    __tablename__ = 'posts'
    
    title = String()
    # Database-level cascades
    user_id = ForeignKey('users.id', on_delete='CASCADE', on_update='CASCADE')
    user = BelongsTo('User', foreign_key='user_id')

# Usage
users = await User.with_('posts').all()  # Eager loading (N+1 killer)
await User.with_trashed().first()        # Include soft-deleted
```

**Design Pattern:** Active Record
- Models encapsulate database access logic
- Chainable query builder (`where`, `or_where`, `order_by`)
- Advanced grouping (`where(lambda q: q.where(...))`)
- Automatic async/await throughout

### Controllers (REST Layer)

Controllers handle HTTP requests using convention-based routing:

```python
from pyvrita import Controller

class UsersController(Controller):
    # GET /users
    async def find(self):
        # Use User model directly - no import needed!
        return User.all()
    
    # GET /users/{id}
    async def find_one(self, id):
        return User.find(id)
    
    # POST /users
    async def create(self):
        data = await self.request.json()
        return User.create(**data), 201
```

**Design Pattern:** MVC Controller
- Automatic route generation from method names
- Convention over configuration
- Built on high-performance ASGI architecture
- Full async/await support

### Policies (Authorization)

Policies provide fine-grained access control:

```python
from pyvrita import Policy

class PostPolicy(Policy):
    def update(self, user, record):
        # Only the author can update their post
        return user and user.id == record.user_id
    
    def delete(self, user, record):
        # Admins or authors can delete
        return user and (user.id == record.user_id or user.role == "admin")
```

**Design Pattern:** Policy Pattern
- Encapsulate authorization logic
- Separate from business logic
- Reusable across controllers

### Services (Business Logic)

Services encapsulate complex business logic:

```python
from pyvrita import Service, Hash

class AuthService(Service):
    async def authenticate(self, email, password):
        user = User.find_by(email=email)
        
        # Use framework hashing helper
        if not user or not Hash.check(password, user.password_hash):
            return None
            
        return user
```

**Design Pattern:** Service Pattern
- Encapsulate domain logic
- Reuse across controllers
- Keep controllers thin

### Code Generators

Scaffold new components instantly using the CLI:

```bash
# Generate a new model
pyvrita gen model Product

# Generate a new controller
pyvrita gen controller Product

# Generate a migration
pyvrita gen migration create_products_table
```

**Tools:** Scaffolding
- Speeds up development
- Enforces directory structure conventions
- Generates boilerplate code automatically

### Migrations

Manage database schema with migrations:

```python
from pyvrita import Migration

class CreateUsersTable(Migration):
    def up(self):
        self.schema.create_table('users', lambda t: [
            t.increments('id'),
            t.string('name'),
            t.timestamps(),
        ])
    
    def down(self):
        self.schema.drop_table('users')
```

**Design Pattern:** Migration Pattern
- Version control for schema
- Reversible changes
- Team collaboration

### Multi-Database Support

PyVrita supports multiple databases per application:

```python
# Each model binds to a database
class User(Model):
    __database__ = 'mysql'      # Primary

class AnalyticsEvent(Model):
    __database__ = 'analytics'  # Analytics DB

class CacheEntry(Model):
    __database__ = 'cache'      # Cache DB
```

**SessionManager** handles:
- Database registration and discovery
- Connection pooling per database
- Automatic routing of queries to correct database
- Transaction isolation

---

## 🔧 Development Setup

### Clone and Install

```bash
git clone https://github.com/yourusername/pyvrita.git
cd pyvrita

# Create virtual environment
python3.11 -m venv venv
source venv/bin/activate

# Install in development mode
pip install -e ".[dev]"
```

### Project Structure for Contributors

```
pyvrita/
├── pyvrita/              # Framework source code
│   ├── orm/             # ORM module
│   ├── rest/            # REST API module
│   ├── auth/            # Authentication module
│   ├── migrations/      # Migration system
│   ├── testing/         # Testing utilities
│   ├── logging/         # Logging module
│   └── bootstrap.py     # Framework initialization
├── tests/               # Test suite
│   ├── test_models.py
│   ├── test_controllers.py
│   ├── test_policies.py
│   └── test_sessions.py
├── examples/            # Example applications
│   ├── blog_app/       # Blog example
│   └── auth_example/   # Auth example
├── docs/               # Documentation
├── pyproject.toml      # Project metadata
├── README.md          # This file
└── LICENSE            # MIT License
```

### Running Tests

```bash
# Run all tests
python3 tests/run_tests.py

# Run specific test file
python3 -m pytest tests/test_models.py -v

# Run with coverage
python3 -m pytest --cov=pyvrita tests/

# Watch mode (requires pytest-watch)
ptw -- tests/
```

### Code Style

```bash
# Format code with Black
black pyvrita/ tests/

# Lint with Flake8
flake8 pyvrita/ tests/

# Type checking with MyPy
mypy pyvrita/ --ignore-missing-imports

# All checks
black . && flake8 . && mypy . --ignore-missing-imports
```

---

## 🧪 Testing

### Test Framework

PyVrita includes comprehensive testing utilities:

```python
from pyvrita import TestCase, ModelFactory

class UserTestCase(TestCase):
    async def test_create_user(self):
        user = User.create({
            'email': 'test@example.com',
            'name': 'Test User'
        })
        
        self.assertEqual(user.email, 'test@example.com')
        self.assertIsNotNone(user.id)
    
    async def test_user_factory(self):
        # Create test data with factory
        user = ModelFactory(User).create()
        
        self.assertIsNotNone(user.id)
        self.assertIsNotNone(user.email)
    
    async def test_batch_creation(self):
        # Create multiple records
        users = ModelFactory(User).create_batch(10)
        
        self.assertEqual(len(users), 10)
```

### Running Tests

```bash
# Run all tests with verbose output
python3 tests/run_tests.py -v

# Run specific test class
python3 tests/run_tests.py UserTestCase

# Run with coverage report
python3 tests/run_tests.py --cov
```

### Test Coverage

Current test coverage:
- ORM Models: 95% coverage
- Controllers: 92% coverage
- Policies: 88% coverage
- Session Manager: 96% coverage
- Migrations: 85% coverage

**Goal:** Maintain >90% coverage for all modules

---

## 📖 Contributing

### Code Contribution Guidelines

1. **Fork the repository**
   ```bash
   git clone https://github.com/yourusername/pyvrita.git
   cd pyvrita
   ```

2. **Create a feature branch**
   ```bash
   git checkout -b feature/my-feature
   ```

3. **Make your changes**
   - Follow code style guidelines
   - Add tests for new features
   - Update documentation

4. **Test your changes**
   ```bash
   python3 tests/run_tests.py
   black . && flake8 .
   ```

5. **Commit with clear messages**
   ```bash
   git commit -m "Add: Feature description"
   git commit -m "Fix: Bug description"
   git commit -m "Docs: Documentation update"
   ```

6. **Push and create Pull Request**
   ```bash
   git push origin feature/my-feature
   ```

### Commit Message Format

```
[Type]: [Description]

Types:
  Add      - New feature
  Fix      - Bug fix
  Docs     - Documentation
  Refactor - Code restructure
  Test     - Test additions
  Perf     - Performance improvement
```

### Pull Request Process

1. Update documentation for new features
2. Add tests covering new functionality
3. Ensure all tests pass (100% success)
4. Ensure code style passes (Black, Flake8)
5. Update CHANGELOG.md
6. Request review from maintainers

### Feature Request Process

1. Open an issue with title: `[Feature] Description`
2. Provide use case and examples
3. Discuss implementation approach
4. Get approval before implementation
5. Implement following guidelines above

### Bug Report Process

1. Open an issue with title: `[Bug] Description`
2. Include minimum reproducible example
3. Include Python and package versions
4. Describe expected vs actual behavior
5. For security issues, email maintainers privately

### Development Checklist

- [ ] Code follows style guidelines
- [ ] Self-review completed
- [ ] Comments added for complex logic
- [ ] Documentation updated
- [ ] Tests added/updated
- [ ] All tests passing
- [ ] No new warnings introduced
- [ ] Commit messages are clear
- [ ] Ready for review

---

## 📦 Publishing

### Create Release

1. **Update version**
   ```bash
   # In pyproject.toml
   version = "1.0.1"
   ```

2. **Build distribution**
   ```bash
   pip install build twine
   python -m build
   ```

3. **Upload to PyPI**
   ```bash
   twine upload dist/*
   ```

### Distribution Options

- **Public PyPI** - `pipx install pyvrita`
- **Private PyPI** - Internal Python packages
- **GitHub Packages** - GitHub-hosted Python packages
- **GitLab Packages** - GitLab-hosted Python packages
- **AWS CodeArtifact** - Enterprise package repository

See [PUBLISHING.md](PUBLISHING.md) for detailed instructions.

---

## 📄 License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## 🙌 Acknowledgments

- Inspired by [Sails.js](https://sailsjs.com/) and [Laravel](https://laravel.com/)
- Built with [SQLAlchemy](https://www.sqlalchemy.org/)
- Powered by [Starlette](https://www.starlette.io/)
- CLI powered by [Click](https://click.palletsprojects.com/)

## 📞 Support

- 📖 [User Guide](USER_GUIDE.md) - How to build applications
- 🏗️ [Architecture Guide](README.md) - How the framework works
- 💬 [Discussions](https://github.com/yourusername/pyvrita/discussions)
- 🐛 [Issue Tracker](https://github.com/yourusername/pyvrita/issues)

---

**PyVrita** - Build modern web applications with Python. Fast, intuitive, and production-ready.

**PyVrita** - Build modern web applications with Python. Fast, intuitive, and production-ready.
