Skip to content

Commit 1ba6f91

Browse files
committed
Contributor's guide
1 parent 873c8a8 commit 1ba6f91

File tree

3 files changed

+285
-6
lines changed

3 files changed

+285
-6
lines changed

CONTRIBUTING.md

Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
WordLoom Contributor Guide
2+
3+
# Quick Reference
4+
5+
## Daily Development
6+
7+
```bash
8+
# Install in current virtualenv
9+
uv pip install -U .
10+
11+
# Run tests
12+
pytest test/ -v
13+
14+
# Run specific test file
15+
pytest test/test_basics.py -v
16+
17+
# Run linting
18+
ruff check .
19+
20+
# Auto-fix linting issues
21+
ruff check --fix .
22+
23+
# Run tests with coverage
24+
pytest test/ --cov=wordloom --cov-report=html
25+
```
26+
27+
## Making Changes
28+
29+
```bash
30+
# After editing any Python files in pylib/
31+
uv pip install -U .
32+
33+
# After editing resources/
34+
uv pip install -U .
35+
36+
# After editing tests only (no reinstall needed)
37+
pytest test/ -v
38+
```
39+
40+
## Useful Commands
41+
42+
```bash
43+
# See package structure after install
44+
python -c "import wordloom, os; print(os.path.dirname(wordloom.__file__))"
45+
ls -la $(python -c "import wordloom, os; print(os.path.dirname(wordloom.__file__))")
46+
47+
# Check what files are in the installed package
48+
pip show -f wordloom
49+
50+
# Check installed version
51+
python -c "import wordloom; print(wordloom.__version__)"
52+
53+
# Compare source version
54+
cat pylib/__about__.py
55+
56+
# Uninstall completely
57+
pip uninstall wordloom -y
58+
59+
# Clean build artifacts
60+
rm -rf build/ dist/ *.egg-info
61+
rm -rf .pytest_cache .ruff_cache
62+
find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
63+
```
64+
65+
## Testing Package Build Locally
66+
67+
```bash
68+
# Build locally
69+
python -m build
70+
python -m build -w # For some reason needs to need both, in this order. Probably an issue in how we're using hatch
71+
72+
# Test the built wheel
73+
pip install dist/wordloom-0.X.Y-py3-none-any.whl --force-reinstall
74+
75+
# Check package contents
76+
unzip -l dist/wordloom-0.X.Y-py3-none-any.whl
77+
```
78+
79+
# Project Structure
80+
81+
```
82+
WordLoom/
83+
├── pylib/ # Source code (becomes 'wordloom' package)
84+
│ ├── __init__.py
85+
│ ├── __about__.py # Version info
86+
│ └── wordloom.py # Main implementation
87+
├── resources/ # Bundled resources
88+
│ └── wordloom/
89+
│ └── sample.toml
90+
├── test/ # Tests
91+
│ ├── test_basics.py
92+
│ ├── test_i18n_integration.py
93+
│ └── test_openai_integration.py
94+
├── pyproject.toml # Project config
95+
└── README.md
96+
97+
When installed, becomes:
98+
site-packages/
99+
└── wordloom/
100+
├── __init__.py
101+
├── __about__.py
102+
├── wordloom.py
103+
└── resources/
104+
└── wordloom/
105+
└── sample.toml
106+
```
107+
108+
When installed, becomes:
109+
110+
```
111+
site-packages/
112+
└── wordloom/
113+
├── __init__.py
114+
├── __about__.py
115+
├── wordloom.py
116+
└── resources/
117+
└── wordloom/
118+
└── sample.toml
119+
```
120+
121+
## Key Files
122+
123+
- `pylib/__about__.py` - Version number (update for releases)
124+
- `pyproject.toml` - Dependencies, metadata, build config
125+
- `resources/wordloom/sample.toml` - Sample file used by tests
126+
- `README.md` - Main documentation
127+
- `wordloom_spec.md` - Format specification (CC BY 4.0)
128+
129+
# Publishing a Release
130+
131+
Before creating a release:
132+
133+
- [ ] Update version in `pylib/__about__.py`
134+
- [ ] Update CHANGELOG.md
135+
- [ ] Run tests locally: `pytest test/ -v`
136+
- [ ] Run linting: `ruff check .`
137+
- [ ] Commit and push all changes
138+
<!--
139+
- [ ] Create git tag: `git tag v0.X.Y`
140+
- [ ] Push tag: `git push origin v0.X.Y`
141+
-->
142+
- [ ] [Create GitHub release](https://github.com/OoriData/WordLoom/releases/new) (triggers publish workflow)
143+
- [ ] Verify package update on PyPI: https://pypi.org/project/wordloom/
144+
145+
## Testing the Package
146+
147+
After publishing, test the installation:
148+
149+
```bash
150+
# Create a fresh virtual environment
151+
python -m venv test_env
152+
source test_env/bin/activate # On Windows: test_env\Scripts\activate
153+
154+
# Install from PyPI
155+
pip install wordloom
156+
157+
# Test import
158+
python -c "import wordloom; print(wordloom.__version__)"
159+
160+
# Test basic functionality
161+
python -c "
162+
import wordloom
163+
import io
164+
165+
toml_data = b'''
166+
lang = 'en'
167+
[test]
168+
_ = 'Hello'
169+
'''
170+
171+
loom = wordloom.load(io.BytesIO(toml_data))
172+
print(loom['test'])
173+
"
174+
```
175+
176+
# Initial Project Setup
177+
178+
Historical, and to inform maintenance. GitHub Actions & PyPI publishing.
179+
180+
## GitHub Actions Setup
181+
182+
The repository includes two workflows:
183+
184+
### 1. CI Workflow (`.github/workflows/main.yml`)
185+
186+
Runs automatically on every push and pull request. It:
187+
- Tests on Python 3.12 and 3.13
188+
- Runs ruff linting
189+
- Runs pytest test suite
190+
191+
### 2. Publish Workflow (`.github/workflows/publish.yml`)
192+
193+
Runs when you create a new GitHub release. It builds and publishes to PyPI.
194+
195+
## PyPI Trusted Publishing Setup
196+
197+
### PyPI Setup
198+
199+
- Login your [PyPI](https://pypi.org) account
200+
- For new package:
201+
- Go to: https://pypi.org/manage/account/publishing/
202+
- Click "Add a new pending publisher"
203+
- Fill in:
204+
- **PyPI Project Name**: `wordloom` (must match `name` in `pyproject.toml`, with case)
205+
- **Owner**: `OoriData`
206+
- **Repository name**: `WordLoom`
207+
- **Workflow name**: `publish.yml`
208+
- **Environment name**: `pypi` (PyPI's recommended name)
209+
- If the package already exists on PyPI:
210+
- Go to the project page: https://pypi.org/manage/project/wordloom/settings/publishing/
211+
- Add the publisher configuration as above
212+
213+
### GitHub Setup
214+
- Go to: https://github.com/OoriData/WordLoom/settings/environments
215+
- Click "New environment"
216+
- Name: `pypi`
217+
- Click "Configure environment"
218+
- (Optional) Add protection rules:
219+
- Required reviewers: Add yourself to require manual approval before publishing
220+
- Wait timer: Add a delay (e.g., 5 minutes) before publishing
221+
- Click "Save protection rules"
222+
223+
### Note on using the environment name
224+
225+
Using an environment name (`pypi`) adds an extra layer of protection, with rules such as required reviewers (manual approval before publishing), wait timers (delay before publishing) and branch restrictions. Without an environment stipulation the workflow runs automatically when a release is created.
226+
227+
## First Time Publishing
228+
229+
Option on the very first release to PyPI: may want to do a manual publish to ensure everything is set up correctly:
230+
231+
```bash
232+
# Install build tools
233+
pip install build twine
234+
235+
# Build the package
236+
python -m build
237+
238+
# For some reason, the wheel only seems to work if you build first without then with `-w`
239+
python -m build -w
240+
241+
# Basic build check
242+
twine check dist/*
243+
244+
# Extra checking
245+
VERSION=0.10.0 pip install --force-reinstall -U dist/wordloom-$VERSION-py3-none-any.whl
246+
python -c "from wordloom import load"
247+
248+
# Upload to Test PyPI first (optional but recommended)
249+
twine upload --repository testpypi dist/*
250+
# Username: __token__
251+
# Password: your-test-pypi-token
252+
253+
# If test looks good, upload to real PyPI
254+
twine upload dist/*
255+
# Username: __token__
256+
# Password: your-pypi-token
257+
```
258+
259+
After the first manual upload, you can use trusted publishing for all future releases.
260+
261+
## Troubleshooting
262+
263+
### "Project name 'wordloom' is not valid"
264+
- Check that the name in `pyproject.toml` matches exactly
265+
- Names are case-insensitive but must match what you registered on PyPI
266+
267+
### "Invalid or non-existent authentication information"
268+
- For trusted publishing: Double-check the repository name, owner, and workflow name
269+
- For token auth: Make sure the token is saved as `PYPI_API_TOKEN` in GitHub secrets
270+
271+
### Workflow fails with "Resource not accessible by integration"
272+
- Make sure the workflow has `id-token: write` permission
273+
- Check that the repository settings allow GitHub Actions
274+
275+
### Package version already exists
276+
- You can't overwrite versions on PyPI
277+
- Increment the version in `pylib/__about__.py` and create a new release
278+
279+
## Additional Resources
280+
281+
- [PyPI Trusted Publishing Guide](https://docs.pypi.org/trusted-publishers/)
282+
- [GitHub Actions for Python](https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python)
283+
- [Python Packaging Guide](https://packaging.python.org/en/latest/)

README.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,7 @@ This is an under-considered area in AI prompting. When dealing with multiple lan
102102

103103
# Contributing
104104

105-
Contributions welcome! This is an early-stage format, and we're interested in feedback from the community about what works and what doesn't in real-world usage.
106-
107-
<!-- For maintainers, see:
108-
- [SETUP_GUIDE.md](SETUP_GUIDE.md) - GitHub Actions and PyPI publishing setup
109-
- [QUICK_REFERENCE.md](QUICK_REFERENCE.md) - Common development tasks -->
105+
Contributions welcome! We're interested in feedback from the community about what works and what doesn't in real-world usage. To get help with the code implementation, read [CONTRIBUTING.md](CONTRIBUTING.md).
110106

111107
# License
112108

pylib/__about__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
# SPDX-License-Identifier: Apache-2.0
44
# wordloom.about
55

6-
__version__ = '0.10.0'
6+
__version__ = '0.10.1'

0 commit comments

Comments
 (0)