Skip to main content

A Spring Boot-inspired Python web framework built on Starlette

Project description

StarSpring Framework

Python Version License Status

StarSpring is a production-grade, asynchronous web framework for Python that brings the robust architectural patterns of Spring Boot to the modern Python ecosystem. Built on top of Starlette and SQLAlchemy, it combines enterprise structure with Pythonic elegance.


🌟 Features

  • Dependency Injection (IoC): Fully typed, automatic constructor injection. No more global state or manual wiring.
  • Declarative Routing: Use @GetMapping, @PostMapping decorators for clean, readable controllers.
  • Enterprise ORM: Built on SQLAlchemy with Imperative Mapping. Define simple Python classes, and they become powerful database entities automatically.
  • Magic Repositories: Define interfaces, and StarSpring implements the queries for you (e.g., find_by_email_and_active(email, True)).
  • Robust Transaction Management: @Transactional decorators with support for robust nested transactions (SAVEPOINTs).
  • Production Ready: Built-in support for CORS, Exception Handling, Logging, and Configuration Management (application.yaml).

📦 Installation

StarSpring requires Python 3.10+.

Using pip

pip install starspring

Using uv (Recommended for speed)

uv pip install starspring

Database Drivers

StarSpring uses SQLAlchemy. Install the driver for your database:

# SQLite (Standard)
pip install starspring

# PostgreSQL
pip install psycopg2-binary
# or
pip install asyncpg

🚀 Building Your First Application

Here is a complete walkthrough of building a User Management API.

1. Project Structure

We recommend a standard layered architecture:

my_app/
├── __init__.py
├── main.py              # Entry point
├── application.yaml     # Configuration
├── entities.py          # Database Models
├── repositories.py      # Data Access
├── services.py          # Business Logic
└── controllers.py       # REST Endpoints

2. Configuration (application.yaml)

Configure your server and database connection.

server:
  port: 8000
  host: 0.0.0.0

database:
  url: "sqlite:///app.db"  # or postgresql://user:pass@localhost/db
  ddl-auto: "create-if-not-exists" # Auto-creates tables from entities

3. Entities (entities.py)

Define your database models using standard Python classes. StarSpring maps them automatically.

from starspring import Entity, BaseEntity, Column
from datetime import datetime

@Entity(table_name="users")
class User(BaseEntity):
    # BaseEntity automatically adds 'id', 'created_at', 'updated_at'
    
    username: str = Column(unique=True, length=50, nullable=False)
    email: str = Column(unique=True, nullable=False)
    is_active: bool = Column(default=True)
    role: str = Column(default="USER")

4. Repositories (repositories.py)

Create an interface for data access. Inherit from StarRepository. Note: Identify the Entity type in the generic (e.g., [User]).

from starspring import Repository, StarRepository
from my_app.entities import User

@Repository
class UserRepository(StarRepository[User]):
    # StarSpring automatically implements standard CRUD (save, find_by_id, delete, etc.)
    
    # Define custom finders just by naming them!
    async def find_by_username(self, username: str) -> User | None:
        ...
        
    async def find_by_email_and_is_active(self, email: str, is_active: bool) -> User | None:
        ...

5. Services (services.py)

Encapsulate your business logic here. Use @Transactional to ensure data integrity.

from starspring import Service, Transactional
from my_app.repositories import UserRepository
from my_app.entities import User

@Service
class UserService:
    # Dependency Injection: Just mention the type in the constructor!
    def __init__(self, user_repo: UserRepository):
        self.user_repo = user_repo

    @Transactional
    async def register_user(self, username: str, email: str) -> User:
        # Check if exists
        existing = await self.user_repo.find_by_email_and_is_active(email, True)
        if existing:
            raise ValueError("User already exists")
            
        # Create new user
        new_user = User(username=username, email=email)
        return await self.user_repo.save(new_user)

6. Controllers (controllers.py)

Expose your logic as a REST API.

# Note: Use @Controller for REST endpoints too. 
# StarSpring automatically serializes dict/list responses to JSON.
from starspring import Controller, GetMapping, PostMapping, ResponseEntity
from my_app.services import UserService

@Controller("/api/users")
class UserController:
    
    def __init__(self, user_service: UserService):
        self.user_service = user_service

    @GetMapping("/{username}")
    async def get_user(self, username: str) -> dict:
        # You can return dicts, lists, or Entities directly
        user = await self.user_service.user_repo.find_by_username(username)
        # Assuming BaseEntity has .to_dict() or Pydantic serialization
        return user.to_dict() if user else ResponseEntity.not_found()

    @PostMapping("/register")
    async def register(self, username: str, email: str) -> dict:
        # Arguments are automatically extracted from JSON body or Query params
        try:
            user = await self.user_service.register_user(username, email)
            return {"status": "success", "user_id": user.id}
        except ValueError as e:
            return ResponseEntity.bad_request(str(e))

7. Main Entry Point (main.py)

Bootstrap the application.

from starspring import StarSpringApplication

# Initialize App
app = StarSpringApplication(
    title="My User API",
    config_path="application.yaml"
)

# Scan for all your components (Controllers, Services, Repositories)
app.scan_components("my_app")

if __name__ == "__main__":
    # Runs the server (default: localhost:8000)
    app.run() 

📚 Core Concepts

Dependency Injection (DI)

StarSpring manages the lifecycle of your objects. When you ask for a UserRepository in your UserService constructor, the framework:

  1. Finds the UserRepository class.
  2. Creates an instance of it (Singleton by default).
  3. Passes it to your UserService.

This makes testing easier (you can mock repositories) and code cleaner.

Database & ORM

We use a Code-First approach.

  1. Define Python classes (@Entity).
  2. StarSpring tells SQLAlchemy to map these classes to tables.
  3. If database.ddl-auto is set to create, the framework creates the tables for you on startup.

Transaction Management

Use the @Transactional decorator on any method (usually in Services).

  • Success: The transaction commits automatically.
  • Reference Counter: If you nest @Transactional methods, the inner one joins the outer transaction.
  • Error: If an exception occurs, the entire transaction rolls back.

🛠 Advanced Configuration

You can tune every part of the framework via application.yaml.

server:
  port: 8080
  cors:
    allowed-origins: ["*"]
    allowed-methods: ["GET", "POST", "PUT", "DELETE"]

logging:
  level: INFO
  format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"

🤝 Contributing

We welcome contributions!

  1. Fork the repository.
  2. Create a feature branch.
  3. Submit a Pull Request.

Please ensure all tests pass before submitting.

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

starspring-0.1.1.tar.gz (40.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

starspring-0.1.1-py3-none-any.whl (47.0 kB view details)

Uploaded Python 3

File details

Details for the file starspring-0.1.1.tar.gz.

File metadata

  • Download URL: starspring-0.1.1.tar.gz
  • Upload date:
  • Size: 40.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for starspring-0.1.1.tar.gz
Algorithm Hash digest
SHA256 ff49ce8565e419920adbc1e2e0b2737e973a0a5492c5f5b98675b3b7f91f3fa8
MD5 7cd3a0505f5cb9312e1b818e580ef207
BLAKE2b-256 6cfa5d5d1170286d27b27d3656c5e3d1d1407ede47d40c927cb58554b1ba59d0

See more details on using hashes here.

File details

Details for the file starspring-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: starspring-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 47.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for starspring-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 6e6712ad96e98e0fa5c6b5f2343f6cb798b4f96907235d646d6495ef860bcb8e
MD5 03cf71ec2563f568aef914f13da6db91
BLAKE2b-256 f381fd021fe96bda824d93eba903a44105b68a014539de0c0d8f2fbca8a7143f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page