Metadata-Version: 2.3
Name: normschores
Version: 0.1.0
Summary: Structural household model of gender norms and the division of market work, chores and leisure.
Author: Thomas H. Jørgensen, Adam Hallengreen
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: C++
Classifier: Operating System :: Microsoft :: Windows
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering
Requires-Dist: matplotlib>=3.11.1
Requires-Dist: numpy>=2.5.1
Requires-Dist: pandas>=3.0.5
Requires-Dist: polars>=1.44
Requires-Dist: pyfixest>=0.60
Requires-Dist: scipy>=1.18.0
Requires-Dist: ipykernel>=7.3.0 ; extra == 'notebooks'
Requires-Dist: papermill>=2.6.0 ; extra == 'notebooks'
Requires-Python: >=3.12
Project-URL: Repository, https://github.com/ThomasHJorgensen/NormsChores
Provides-Extra: notebooks
Description-Content-Type: text/markdown

# normschores

Code for the NormsChores project: a structural household model of gender norms and the division of
market work, chores and leisure, with simulated-minimum-distance estimation tools.

The Python package lives in `src/normschores/`:

| module | contents |
| --- | --- |
| `normschores.Chorms` | `ChormsClass`, the model (solved in C++, see `cppfuncs/`) |
| `normschores.estimate` | moments (`moments`), bootstrap covariance (`bootstrap_cov`), SMD estimator (`SMD`) |
| `normschores.exhibits` | figures and tables for the paper |
| `normschores.LocalEconModel` | vendored copy of [EconModel](https://github.com/NumEconCopenhagen/EconModel) used for the C++ linking |
| `normschores/notebooks/` | the notebooks that reproduce the paper (`0_DataMoments.ipynb`, `1_EstimateModel.ipynb`, ..., `_ Run all notebooks.ipynb`) |

## Requirements

**Windows only.** The model is solved in C++ which is compiled on first use with Microsoft Visual
Studio (2019/2022 Community is found automatically; for other editions set `COMPILER_PATH` in the
notebooks, or pass `ChormsClass(..., compiler_path="<VS>/VC/Auxiliary/Build/")`). The compiled
`model_cpp.dll` is written to the current working directory. Python 3.12 or newer.

## Running the notebooks from the published package

Create a fresh virtual environment, install the package with the `notebooks` extra (adds `ipykernel`
and `papermill`) and copy the notebooks to a working folder. The notebooks write their results
(`saved/`, `output/figures/`, `output/tables/`) relative to the folder they are run from, so always
run them from such a copy, never from inside the installed package.

With [uv](https://docs.astral.sh/uv/):

```bash
uv venv --python 3.12 .venv
.venv\Scripts\activate
uv pip install "normschores[notebooks]"
normschores-notebooks my_run      # copies the notebooks to .\my_run
```

or with plain pip:

```bash
py -3.12 -m venv .venv
.venv\Scripts\activate
pip install "normschores[notebooks]"
normschores-notebooks my_run
```

Then open the notebooks in `my_run` with `.venv\Scripts\python.exe` as the kernel (in VS Code:
*Select Kernel → Python Environments*; for a browser, also `pip install jupyterlab`) and run
`_ Run all notebooks.ipynb`, or the notebooks one at a time in numbered order. `normschores-notebooks`
refuses to overwrite notebooks already in the folder unless `--force` is given.

The model can also be used directly:

```python
from normschores import ChormsClass

model = ChormsClass(name="baseline")
model.link_to_cpp()   # compiles cppfuncs/model_cpp.cpp shipped with the package
```

## Development setup (repository)

In the repository the notebooks are edited and run in place in `src/normschores/notebooks/`. Their
results (`saved/`, `output/`) are kept next to them but are not included in the built package. The
paper reads the figures and tables from there (`\codefigs`/`\codetabs` in `_main.tex`).

Move to the `code` directory and run:

### Option A — uv

```bash
uv sync
```

This creates `.venv`, installs `normschores` in editable mode (so changes in `src/` are picked up
directly) and the notebook tools (`ipykernel`, `papermill`) from the `dev` dependency group.

Activate the environment:

```bash
# Windows
.venv\Scripts\activate

# Linux / macOS
source .venv/bin/activate
```

For Jupyter notebooks in VS Code, the kernel is located at `.venv\Scripts\python.exe`.

### Option B — pip + venv

```bash
python -m venv .venv

# Windows
.venv\Scripts\activate
# Linux / macOS
source .venv/bin/activate

pip install -r requirements.txt
```

### Option C — Anaconda / conda

```bash
conda env create -f environment.yml
conda activate normschores
```

---

## Releasing

Builds use [uv](https://docs.astral.sh/uv/) (`uv build`, with the `uv_build` backend). Publishing
is done by the GitHub Actions workflow `.github/workflows/publish.yml` (in the repository root).

To publish a new version to PyPI:

```bash
uv version --bump patch      # or minor / major; updates pyproject.toml and uv.lock
git commit -am "Release v$(uv version --short)"
git tag "v$(uv version --short)"
git push && git push --tags
```

Pushing a `v*` tag runs the workflow, which builds the package and uploads it to PyPI with trusted publishing (no API token stored in GitHub).

One-time setup on PyPI: under *Your projects → Publishing* add a pending trusted publisher with
owner `ThomasHJorgensen`, repository `NormsChores`, workflow `publish.yml` and environment `pypi`.
Also create an environment named `pypi` in the GitHub repository settings.

## Appendix: Maintaining dependency files

### Updating `requirements.txt`

`requirements.txt` is generated by uv from `pyproject.toml`. After adding or upgrading
packages in `pyproject.toml`, regenerate it with:

```bash
uv lock
uv export --no-hashes -o requirements.txt
```
