Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,8 @@ src/palace/manager/core/_version.py

# Celery beat schedule file
celerybeat-schedule.db

# Claude
.claude/
!.claude/settings.json
CLAUDE.local.md
1 change: 1 addition & 0 deletions AGENTS.md
191 changes: 191 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
# Project: Palace Manager

## Project Description

Palace Manager is a backend service that powers digital library systems.
It enables library patrons to discover, borrow, hold, return, and consume
digital content including audiobooks, e-books, and other digital media
through mobile and web applications.

## Tech Stack

**Core Framework:**

- Python 3.12+
- Flask

**Data & Storage:**
- PostgreSQL
- Redis
- OpenSearch
- SQLAlchemy
- alembic (database migrations)
- Pydantic

**Background Processing:**
- Celery

**Development & Testing:**
- pytest, tox
- Poetry (package management)
- pre-commit (linting/formatting)
- mypy (type checking)

## Code Conventions

- Pre-commit for linting/formatting code
- Poetry for package management
- `pyproject.toml` for project configuration
- Doc comments use reStructuredText style
- Type hint all code with mypy validation
- Follow existing naming conventions and patterns
- Use f-strings for string formatting
- Whenever possible, you should do imports at the top of the file.
If you need to do a local import, please add a comment explaining why.
- Instead of using generic exceptions. All the exceptions we raise should be subclasses of BasePalaceException, defined
in src/palace/manager/core/exceptions.py. There are some Palace versions of common exceptions defined in that file like
`PalaceValueError` or `PalaceTypeError`.
- Whenever possible use immutable datastructures for global and class constants.

## Project Structure

- `/src/palace/manager` - Main application source code
- `/api` - REST API endpoints for mobile applications
- `/admin` - Administrative API endpoints for the web dashboard
- `/celery` - Background worker processes and task definitions
- `/core` - Legacy miscellaneous components (**deprecated - no new code**)
- `/customlists` - CLI tools for managing custom book collections
- `/data_layer` - Pydantic models for content import and validation
- `/feed` - OPDS (Open Publication Distribution System) feed generation
- `/integration` - Third-party service integrations and content provider APIs
- `/opds` - Pydantic models for OPDS feed parsing and validation
- `/scripts` - Legacy CLI utilities (**deprecated - no new code**)
- `/search` - OpenSearch integration and indexing logic
- `/service` - Dependency injection container and service layer
- `/sqlalchemy` - Database models and schema definitions
- `/util` - Reusable utility functions and helpers
- `/tests` - Test files
- `/files` - Test fixture files
- `/fixtures` - pytest fixtures shared across test functions
- `/manager` - pytest test files (should mirror `src/palace/manager` structure)
- `/migration` - Database migration tests
- `/mocks` - Test mocks (**being phased out - avoid in new code**)

## Architecture Overview

Palace Manager follows a service-oriented architecture with:

- API layer handling HTTP requests
- Service layer containing business logic
- Data layer managing database operations
- Background workers processing async tasks

## Development Workflow

### Running Tests

```bash
# Run all tests
tox -e py312-docker -- --no-cov

# Run specific test file
tox -e py312-docker -- --no-cov path/to/test_file.py

# Run with coverage (default)
tox -e py312-docker -- path/to/test_file.py
```

### Type Checking

```bash
mypy
```

### Database Migrations

To generate a new migration manually, use the following command:

```bash
alembic revision -m "Migration message"
```

To autogenerate a migration based on model changes:

```bash
SIMPLIFIED_PRODUCTION_DATABASE="postgresql://palace:test@localhost:5432/circ" \
alembic revision --autogenerate -m "Migration message"
```

After creating a migration, the content of the migration file should be reviewed and adjusted as necessary. The
autogenerated comments should be removed, and any complex changes should be explained in comments.

## Contributing Guidelines

- All new features require corresponding tests
- Maintain test coverage above existing levels
- Follow existing naming conventions
- Update documentation for public APIs
- Any new code should have a companion test file
- Branches should be created with the following prefixes:
- `feature/` for new features
- When creating a PR for a feature branch, add the `feature` label to the PR
- `bugfix/` for bug fixes
- When creating a PR for a bugfix branch, add the `bug` label to the PR
- `chore/` for cleanup, refactors, or non-functional changes
- Do not add any labels to PRs for chore branches
- Any PR that contains a database migration should have the `DB migration` label added to it
- Any PR that makes breaking changes to the public API should have the `incompatible changes` label added to it
- Use clear, descriptive commit messages
- When creating a PR always use the template here .github/pull_request_template.md to write the PR description
- Check the correct boxes in the `Checklist` section
- If given a jira ticket number (e.g. PP-123), include it in the PR title
- Example: `Add new feature to manage book loans (PP-123)`

## Instructions for Claude

**Type Annotations:**
- Always add comprehensive type hints for new functions
- Use specific types rather than `Any` when possible
- Import types from `typing` or `collections.abc` as needed
- Example: `def process_books(books: list[Book]) -> dict[str, int]:`
- In the rare case a type ignore is needed, only ignore specific codes
and add a helpful comment explaining exactly why it was needed
- Example: `# type: ignore[code] # detailed explanation`

**Error Handling:**
- Follow existing error handling patterns
- Use custom exceptions defined in the codebase
- Log errors with appropriate severity levels
- Include context in error messages

**Performance:**
- Prioritize performance optimizations
- Use database queries efficiently (avoid N+1 problems)
- Consider caching for expensive operations
- Profile code when performance is critical

**Testing Requirements:**
- Write unit tests for all new functions
- Include integration tests for API endpoints
- Mock external service calls
- Test error conditions and edge cases
- Name test classes after the class or module under test
(e.g., `TestFeed`, `TestPublication`), not after behaviors or scenarios.
Add test methods to the appropriate existing test class rather than
creating new classes for specific scenarios.

**Documentation:**
- Add docstrings to all public functions using restructured text format
- Add a small doc comment to private/internal functions as needed, it doesn't need to be as detailed as public functions
- Update module-level docstrings if functionality changes

**Pre-commit Hooks:**
- When doing a commit, the pre-commit hooks will run automatically
- If any hook fails, it should make the required changes and you should re-stage the files and commit again
- In the case where a pre-commit hook fails, you should not amend the commit message, just re-stage and commit again

### Ongoing updates

- Update CLAUDE.md with any new information about the codebase, architecture, or development practices.
- Whenever making major changes to the project update the CLAUDE.md file accordingly
- When interrupted or given new information, update the CLAUDE.md file so that you do this automatically in the future
Loading