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
1 change: 1 addition & 0 deletions .ai-instructions
Submodule .ai-instructions added at 59ccc0
56 changes: 52 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,59 @@
# Ignore the cloned package repositories in this meta-workspace
ttsim/
gettsim/
gettsim-personas/
soep-preparation/
ttsim/

# Claude Code
.claude/

# Distribution / packaging
*.egg
*.egg-info/
*.manifest
*.spec
.eggs/
.installed.cfg
build/
dist/
MANIFEST
sdist/
wheels/

# Documentation
docs/_build/

# IDE
.idea/
.vscode/

# Jupyter
.ipynb_checkpoints/

# Common local/IDE noise (kept minimal; each repo can have its own .gitignore)
# macOS
.DS_Store
*.pyc
__pycache__/

# pixi
.pixi/
node_modules/

# Python
__pycache__/
*.py[cod]
*.so
*$py.class

# Ruff
.ruff_cache/

# Testing
.cache/
.coverage
.coverage.*
.hypothesis/
.pytest_cache/
coverage.xml
htmlcov/

# Version file (generated by hatch-vcs)
src/*/_version.py
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[submodule ".ai-instructions"]
path = .ai-instructions
url = git@github.com:OpenSourceEconomics/ai-instructions.git
branch = make-submodule
60 changes: 36 additions & 24 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ repos:
- id: check-hooks-apply
- id: check-useless-excludes
# - id: identity # Prints all files passed to pre-commits. Debugging.
- repo: https://github.com/tox-dev/pyproject-fmt
rev: v2.18.1
hooks:
- id: pyproject-fmt
- repo: https://github.com/lyz-code/yamlfix
rev: 1.19.1
hooks:
Expand All @@ -13,51 +17,59 @@ repos:
rev: v6.0.0
hooks:
- id: check-added-large-files
args: [--maxkb=10000]
args:
- --maxkb=10000
- id: check-ast
- id: check-case-conflict
- id: check-docstring-first
- id: check-merge-conflict
- id: check-toml
- id: check-vcs-permalinks
- id: check-yaml
- id: check-toml
- id: debug-statements
- id: end-of-file-fixer
- id: fix-byte-order-marker
types: [text]
- id: forbid-submodules
types:
- text
- id: mixed-line-ending
args: [--fix=lf]
args:
- --fix=lf
description: Forces to replace line ending by the UNIX 'lf' character.
- id: no-commit-to-branch
args: [--branch, main]
args:
- --branch
- main
- id: trailing-whitespace
- id: check-ast
- id: check-docstring-first
- repo: https://github.com/adrienverge/yamllint.git
rev: v1.37.1
rev: v1.38.0
hooks:
- id: yamllint
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.14.10
rev: v0.15.6
hooks:
- id: ruff-check
types_or: [python, jupyter]
args: [--fix]
args:
- --fix
types_or:
- jupyter
- pyi
- python
- id: ruff-format
types_or: [python, jupyter]
types_or:
- jupyter
- pyi
- python
- repo: https://github.com/executablebooks/mdformat
rev: 1.0.0
hooks:
- id: mdformat
additional_dependencies: [mdformat-gfm, mdformat-ruff]
args: [--wrap, '88']
files: (README.md|CHANGES.md|CODE_OF_CONDUCT.md)
# - repo: local
# hooks:
# - id: ty
# name: ty
# entry: ty
# language: system
# types: [python]
# args: [--config-file=pyproject.toml]
additional_dependencies:
- mdformat-gfm
- mdformat-gfm-alerts
- mdformat-ruff
args:
- --wrap
- '88'
files: (AGENTS\.md|CLAUDE\.md|README\.md|CHANGES\.md|CODE_OF_CONDUCT\.md|modules/.*\.md|profiles/.*\.md)
ci:
autoupdate_schedule: monthly
36 changes: 36 additions & 0 deletions .yamllint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
rules:
braces: enable
brackets: enable
colons: enable
commas: enable
comments:
level: warning
comments-indentation:
level: warning
document-end: disable
document-start:
level: warning
empty-lines: enable
empty-values: disable
float-values: disable
hyphens: enable
indentation: {spaces: 2}
key-duplicates: enable
key-ordering: disable
line-length:
allow-non-breakable-inline-mappings: true
allow-non-breakable-words: true
max: 88
new-line-at-end-of-file: enable
new-lines:
type: unix
octal-values: disable
quoted-strings: disable
trailing-spaces: enable
truthy:
level: warning
yaml-files:
- '*.yaml'
- '*.yml'
- .yamllint
94 changes: 94 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
@.ai-instructions/profiles/tier-a.md @.ai-instructions/modules/jax.md
@.ai-instructions/modules/pandas.md @.ai-instructions/modules/optimagic.md
@.ai-instructions/modules/plotting.md @.ai-instructions/modules/project-structure.md
@.ai-instructions/modules/pytask.md @.ai-instructions/modules/ml-econometrics.md

# dev-gettsim

## Overview

This is a [pixi](https://pixi.sh) workspace containing four related projects for the
German tax and transfer microsimulation system:

- **ttsim** (`ttsim/`) - Core computation engine with DAG-based architecture supporting
NumPy and JAX backends
- **gettsim** (`gettsim/`) - German policy implementations (functions, parameters,
tests)
- **gettsim-personas** (`gettsim-personas/`) - Example household personas for testing
and exploration
- **soep-preparation** (`soep-preparation/`) - Data preparation for SOEP survey data

Each subdirectory has its own `CLAUDE.md` with project-specific guidance. Refer to
`ttsim/CLAUDE.md` and `gettsim/CLAUDE.md` for detailed architecture and conventions.

## Build & Test

```bash
# Run all tests across all projects
pixi run -e py314 tests

# Run tests with JAX backend
pixi run -e py314-jax tests-jax

# Run tests for a specific project
pixi run -e py314 tests ttsim/tests/
pixi run -e py314 tests gettsim/src/gettsim/tests_germany/
pixi run -e py314 tests gettsim-personas/tests/
pixi run -e py314 tests soep-preparation/tests/

# Run specific test
pixi run -e py314 tests -k "test_end_to_end"

# Type checking (all projects)
pixi run ty

# Type checking with JAX backend
pixi run ty-jax

# Quality checks (linting, formatting)
prek run --all-files

# Available environments: py314, py314-jax, py314-cuda, py314-metal, type-checking, type-checking-jax
```

## Command Rules

Always use these command mappings:

- **Python**: Use `pixi run python` instead of `python` or `python3`
- **Type checker**: Use `pixi run ty` instead of running ty/mypy/pyright directly
- **Tests**: Use `pixi run tests` instead of `pytest` directly
- **Linting/formatting**: Use `prek run --all-files` instead of `ruff` directly
- **All quality checks**: Use `prek run --all-files`

Before finishing any task that modifies code, always run these three verification steps
in order:

1. `pixi run ty` (type checker)
1. `prek run --all-files` (quality checks: linting, formatting, yaml, etc.)
1. `pixi run -e py314 tests -n 7` (full test suite)

## Architecture

- **Two-level DAG system**: Interface DAG (high-level orchestration) and TT DAG (core
computation)
- **Single entry point**: `gettsim.main()` or `ttsim.main()` with `MainTarget`,
`InputData`, `TTTargets` helpers
- **Backend abstraction**: `"numpy"` or `"jax"` backends; use `xnp(backend)` for array
operations
- **Qualified names (qnames)**: Double-underscore separated paths (e.g.,
`"kindergeld__betrag_m"`)
- **German naming**: Policy code uses German (Kindergeld, Bürgergeld), infrastructure
uses English

## Python Version

The root workspace sets `requires-python = ">=3.11"` to match the most permissive
sub-project (ttsim, gettsim, gettsim-personas all require `>=3.11`; soep-preparation
requires `>=3.14`). The `ty` type checker uses this to determine what's valid at
runtime, so it must stay consistent with the individual projects' constraints.

## pytest Configuration

The workspace uses `--import-mode=importlib` to handle test files with identical names
across projects. This is configured in the root `pyproject.toml`.
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@AGENTS.md
7 changes: 2 additions & 5 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
from __future__ import annotations

from typing import TYPE_CHECKING
from types import ModuleType
from typing import Literal

import pytest
from ttsim.interface_dag_elements.backend import dnp as ttsim_dnp
from ttsim.interface_dag_elements.backend import xnp as ttsim_xnp

if TYPE_CHECKING:
from types import ModuleType
from typing import Literal


def pytest_addoption(parser):
parser.addoption(
Expand Down
Loading