Skip to content

Commit 3c23765

Browse files
authored
Merge pull request #3 from Harshal6927/improv-1
feat: add memory stores
2 parents cd0c6b0 + 570149d commit 3c23765

16 files changed

Lines changed: 394 additions & 61 deletions

AGENTS.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# Agent Guidelines for litestar-start
2+
3+
This document contains instructions for AI agents operating in this repository.
4+
5+
## 1. Build, Lint, and Test Commands
6+
7+
This project uses `uv` for dependency management and `hatchling` for building.
8+
9+
### Dependency Management
10+
- **Install dependencies:** `uv sync`
11+
- **Update lockfile:** `uv lock` (or `uv lock --upgrade` to upgrade)
12+
13+
### Testing
14+
- **Run all tests:**
15+
```bash
16+
pytest
17+
```
18+
- **Run a single test file:**
19+
```bash
20+
pytest tests/test_generator.py
21+
```
22+
- **Run a specific test case:**
23+
```bash
24+
pytest tests/test_generator.py::test_function_name
25+
```
26+
- **Run with verbose output:**
27+
```bash
28+
pytest -v
29+
```
30+
31+
### Linting and Formatting
32+
- **Run all linters (Ruff, Type Checking, Pre-commit):**
33+
```bash
34+
make lint
35+
```
36+
*Note: This runs `ruff check --fix`, `ty check`, and `pre-commit run -a`.*
37+
38+
- **Run Ruff manually:**
39+
```bash
40+
ruff check .
41+
```
42+
43+
- **Run Type Checking manually:**
44+
```bash
45+
ty check
46+
```
47+
48+
## 2. Code Style Guidelines
49+
50+
Adhere strictly to the following conventions to match the existing codebase.
51+
52+
### General
53+
- **Python Version:** Target Python 3.13+.
54+
- **Line Length:** 120 characters (configured in `pyproject.toml`).
55+
- **File Operations:** Always use `pathlib.Path` instead of `os.path` strings.
56+
- **Data Models:** Use `msgspec.Struct` for defining data structures/configurations, not `dataclasses` or `pydantic`.
57+
- **Enums:** Use `enum.StrEnum` for string-based enumerations.
58+
59+
### Imports
60+
- Group imports:
61+
1. Standard library (e.g., `pathlib`, `re`)
62+
2. Third-party libraries (e.g., `jinja2`, `msgspec`)
63+
3. Local application imports (e.g., `src.utils`)
64+
- Imports are sorted automatically by Ruff; attempt to group them logically.
65+
66+
### Typing
67+
- **Strict Typing:** All functions and methods must have type annotations for arguments and return values.
68+
- Use built-in types (`list`, `dict`, `set`) instead of `typing.List`, etc.
69+
- Use `|` for unions (e.g., `str | None`) instead of `Optional` or `Union`.
70+
71+
### Naming Conventions
72+
- **Variables/Functions:** `snake_case`
73+
- **Classes:** `PascalCase`
74+
- **Constants:** `SCREAMING_SNAKE_CASE`
75+
- **Private Members:** Prefix with `_` (though `SLF001` is ignored in Ruff, still prefer public interfaces).
76+
77+
### Docstrings
78+
- Use **Google-style** docstrings for all public modules, functions, classes, and methods.
79+
- Format:
80+
```python
81+
def function(arg: int) -> str:
82+
"""Short summary of the function.
83+
84+
Args:
85+
arg: Description of the argument.
86+
87+
Returns:
88+
Description of the return value.
89+
90+
"""
91+
```
92+
93+
### Error Handling
94+
- Validate inputs early (fail fast).
95+
- Use specific exceptions where possible.
96+
- Avoid bare `except:` blocks.
97+
98+
### Directory Structure
99+
- `src/`: Source code.
100+
- `tests/`: Test files (mirrors source structure or flat list).
101+
- `tools/`: Build and maintenance scripts.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ license = "MIT"
1616
name = "litestar-start"
1717
readme = "README.md"
1818
requires-python = ">=3.13"
19-
version = "0.1.0a16"
19+
version = "0.1.0a17"
2020

2121
[project.scripts]
2222
litestar-start = "src.cli:main"

src/Litestar/App/app.py.jinja

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ from .controllers import UserController
1414
{% if litestar_vite %}
1515
from litestar_vite import ViteConfig, VitePlugin
1616
{% endif %}
17+
{% if has_store %}
18+
from .config import redis_store
19+
{% endif %}
1720

1821
@get("/health")
1922
async def health() -> dict[str, str]:
@@ -40,6 +43,9 @@ app = Litestar(
4043
},
4144
log_exceptions="always",
4245
),
46+
{% if has_store %}
47+
stores={"redis": redis_store},
48+
{% endif %}
4349
{% if advanced_alchemy %}
4450
exception_handlers={
4551
Exception: exception_handler,

src/Litestar/App/config.py.jinja

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ from advanced_alchemy.extensions.litestar import (
99
from pathlib import Path
1010
from litestar_vite import ViteConfig, PathConfig
1111
{% endif %}
12+
{% if has_store %}
13+
from litestar.stores.redis import RedisStore
14+
{% endif %}
1215

1316
from .settings import get_settings
1417

@@ -37,3 +40,11 @@ vite_config = ViteConfig(
3740
),
3841
)
3942
{% endif %}
43+
44+
{% if has_store %}
45+
redis_store = RedisStore.with_client(
46+
url=settings.REDIS_URL,
47+
port=6379,
48+
db=0,
49+
)
50+
{% endif %}

src/Litestar/App/settings.py.jinja

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ class Settings:
4747
{% endif %}
4848
{% endif %}
4949

50+
{% if has_store %}
51+
# Memory Store
52+
REDIS_URL: str = field(
53+
default_factory=lambda: os.getenv("REDIS_URL", "{{ store_config.default_url }}")
54+
)
55+
{% endif %}
56+
5057
@classmethod
5158
def from_env(cls, dotenv_filename: str) -> "Settings":
5259
env_file = (

src/Litestar/Config/.env.example.jinja

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,8 @@ DATABASE_URL=sqlite+aiosqlite:///./app.db
1818
DATABASE_URL=mysql+asyncmy://myuser:mypassword@localhost:3306/mydb
1919
{% endif %}
2020
{% endif %}
21+
22+
{% if has_store %}
23+
# Memory Store
24+
REDIS_URL={{ store_config.default_url }}
25+
{% endif %}

src/Litestar/Config/pyproject.toml.jinja

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ dependencies = [
2020
{% if litestar_vite %}
2121
"litestar-vite>=0.18.1",
2222
{% endif %}
23+
{% if has_store %}
24+
"redis>=5.2.1",
25+
{% endif %}
2326
]
2427

2528
[tool.ruff]

src/Litestar/Containers/docker-compose.infra.yml.jinja

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
services:
22
{% if database.value == "PostgreSQL" %}
33
postgres:
4-
image: postgres:17.7-alpine3.23
4+
image: {{ db_config.docker_image }}
55
container_name: {{ project_slug }}_postgres_dev_db
66
environment:
77
POSTGRES_DB: mydb
@@ -22,7 +22,7 @@ volumes:
2222
{{ project_slug }}_postgres_dev_db: {}
2323
{% elif database.value == "MySQL" %}
2424
mysql:
25-
image: mysql:8.4.8-oraclelinux9
25+
image: {{ db_config.docker_image }}
2626
container_name: {{ project_slug }}_mysql_dev_db
2727
environment:
2828
MYSQL_DATABASE: mydb
@@ -43,3 +43,28 @@ volumes:
4343
volumes:
4444
{{ project_slug }}_mysql_dev_db: {}
4545
{% endif %}
46+
{% if memory_store.value == "Redis" %}
47+
redis:
48+
image: {{ store_config.docker_image }}
49+
container_name: {{ project_slug }}_redis_dev
50+
ports:
51+
- "{{ store_config.port }}:6379"
52+
healthcheck:
53+
test: ["CMD", "redis-cli", "ping"]
54+
interval: 10s
55+
timeout: 5s
56+
retries: 5
57+
restart: unless-stopped
58+
{% elif memory_store.value == "Valkey" %}
59+
valkey:
60+
image: {{ store_config.docker_image }}
61+
container_name: {{ project_slug }}_valkey_dev
62+
ports:
63+
- "{{ store_config.port }}:6379"
64+
healthcheck:
65+
test: ["CMD", "valkey-cli", "ping"]
66+
interval: 10s
67+
timeout: 5s
68+
retries: 5
69+
restart: unless-stopped
70+
{% endif %}

src/Litestar/Containers/docker-compose.yml.jinja

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,33 @@ services:
1818
- DATABASE_URL=sqlite+aiosqlite:///./app.db
1919
{% endif %}
2020
{% endif %}
21+
{% if has_store %}
22+
- REDIS_URL=redis://{{ project_slug }}_{{ memory_store.value|lower }}:6379/0
23+
{% endif %}
2124
env_file:
2225
- .env
23-
{% if database.value == "PostgreSQL" %}
26+
{% if (database.value == "PostgreSQL" or database.value == "MySQL") or has_store %}
2427
depends_on:
28+
{% if database.value == "PostgreSQL" %}
2529
postgres:
2630
condition: service_healthy
27-
{% elif database.value == "MySQL" %}
28-
depends_on:
31+
{% elif database.value == "MySQL" %}
2932
mysql:
3033
condition: service_healthy
34+
{% endif %}
35+
{% if memory_store.value == "Redis" %}
36+
redis:
37+
condition: service_healthy
38+
{% elif memory_store.value == "Valkey" %}
39+
valkey:
40+
condition: service_healthy
41+
{% endif %}
3142
{% endif %}
3243
restart: unless-stopped
3344

3445
{% if database.value == "PostgreSQL" %}
3546
postgres:
36-
image: postgres:17.7-alpine3.23
47+
image: {{ db_config.docker_image }}
3748
container_name: {{ project_slug }}_postgres_db
3849
environment:
3950
POSTGRES_DB: mydb
@@ -51,7 +62,7 @@ services:
5162
restart: unless-stopped
5263
{% elif database.value == "MySQL" %}
5364
mysql:
54-
image: mysql:8.4.8-oraclelinux9
65+
image: {{ db_config.docker_image }}
5566
container_name: {{ project_slug }}_mysql_db
5667
environment:
5768
MYSQL_DATABASE: mydb
@@ -70,6 +81,32 @@ services:
7081
restart: unless-stopped
7182
{% endif %}
7283

84+
{% if memory_store.value == "Redis" %}
85+
redis:
86+
image: {{ store_config.docker_image }}
87+
container_name: {{ project_slug }}_redis
88+
ports:
89+
- "{{ store_config.port }}:6379"
90+
healthcheck:
91+
test: ["CMD", "redis-cli", "ping"]
92+
interval: 10s
93+
timeout: 5s
94+
retries: 5
95+
restart: unless-stopped
96+
{% elif memory_store.value == "Valkey" %}
97+
valkey:
98+
image: {{ store_config.docker_image }}
99+
container_name: {{ project_slug }}_valkey
100+
ports:
101+
- "{{ store_config.port }}:6379"
102+
healthcheck:
103+
test: ["CMD", "valkey-cli", "ping"]
104+
interval: 10s
105+
timeout: 5s
106+
retries: 5
107+
restart: unless-stopped
108+
{% endif %}
109+
73110
{% if database.value == "PostgreSQL" %}
74111
volumes:
75112
{{ project_slug }}_postgres_db: {}

src/Litestar/generator.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from jinja2 import Environment
66

7-
from src.models import DatabaseConfig, ProjectConfig
7+
from src.models import DatabaseConfig, MemoryStoreConfig, ProjectConfig
88
from src.plugin import discover_plugins
99
from src.utils import get_package_dir, get_template_env, write_file
1010

@@ -33,6 +33,7 @@ def _get_template_context(self) -> dict:
3333
3434
"""
3535
db_config = DatabaseConfig.for_database(self.config.database)
36+
store_config = MemoryStoreConfig.for_store(self.config.memory_store)
3637

3738
context = {
3839
"project": self.config,
@@ -41,6 +42,9 @@ def _get_template_context(self) -> dict:
4142
"database": self.config.database,
4243
"db_config": db_config,
4344
"has_database": self.config.database.value != "None",
45+
"memory_store": self.config.memory_store,
46+
"store_config": store_config,
47+
"has_store": self.config.memory_store.value != "None",
4448
"docker": self.config.docker,
4549
"docker_infra": self.config.docker_infra,
4650
}

0 commit comments

Comments
 (0)