Draft
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
10 changes: 5 additions & 5 deletions .github/workflows/test.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,14 +9,14 @@ jobs:
DJANGO_SETTINGS_MODULE: pythonie.settings.tests
steps:
- uses: actions/checkout@v2
- name: Set Up Python 3.12
- name: Set Up Python 3.13
uses: actions/setup-python@v2
Comment on lines +12 to 13

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you consider setup-uv action instead of setup-python? It can install Python versions just fine, and yields a cleaner result in overall config in my experience.

with:
python-version: "3.12"
python-version: "3.13"
- name: Install the dependencies
run: |
python -m pip install --upgrade pip setuptools uv
python -m uv pip install -r requirements/main.txt -r requirements/dev.txt
python -m pip install --upgrade pip uv
uv sync
- name: Run the tests
run: |
python pythonie/manage.py test pythonie --verbosity=2
uv run python pythonie/manage.py test pythonie --verbosity=2
1 change: 1 addition & 0 deletions .tool-versions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
python 3.13.9
task 3.37.2
uv 0.9.18
57 changes: 46 additions & 11 deletions CLAUDE.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,7 +57,8 @@ Always specify settings module: `--settings=pythonie.settings.dev` (or `tests`,
# Setup
python3 -m venv pythonie-venv
source pythonie-venv/bin/activate
pip install -r requirements.txt
pip install uv
uv sync

# Database
python pythonie/manage.py migrate --settings=pythonie.settings.dev
Expand DownExpand Up@@ -128,32 +129,66 @@ task code:check

### Dependency Management

Uses `uv` for fast Python package management. Dependencies are defined in `.in` files and compiled to `.txt` files:
Uses `uv` with `pyproject.toml` for dependency management. Dependencies are defined in `pyproject.toml` and locked in `uv.lock`:

```bash
# Recompile all dependencies
task dependencies:compute
# or: toast deps:compute
**Structure:**
- `pyproject.toml` - Dependency specifications (edit this to add/remove dependencies)
- `uv.lock` - Locked versions (auto-generated, commit to git)
- `requirements.txt` - Auto-generated for Heroku deployment

# Check outdated packages
task dependencies:outdated
**Common Commands:**

```bash
# Update lock file after changing pyproject.toml
task dependencies:lock

# Upgrade all dependencies
task dependencies:upgrade

# Upgrade only Wagtail
task dependencies:upgrade:wagtail

# Upgrade specific package
task dependencies:upgrade:package PACKAGE=django

# Install dependencies (development)
task dependencies:sync

# Install production dependencies only
task dependencies:sync:production

# Generate requirements.txt for Heroku
task dependencies:export

# Check outdated packages
task dependencies:outdated

# Check for security vulnerabilities
task dependencies:security

# Show dependencies tree
task dependencies:tree
```

**Adding a New Dependency:**

1. Edit `pyproject.toml` to add the dependency:
```toml
dependencies = [
"new-package",
# ...
]
```

2. Update lock and generate requirements.txt:
```bash
task dependencies:lock
task dependencies:export
```

3. Commit both files:
```bash
git add pyproject.toml uv.lock requirements.txt
git commit -m "Add new-package dependency"
```

### Database Operations (Heroku)

```bash
Expand Down
3 changes: 2 additions & 1 deletion CONTRIBUTING.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -85,7 +85,8 @@ python3.13 -m venv pythonie-venv
source pythonie-venv/bin/activate

# Install dependencies
pip install -r requirements/dev.txt
pip install uv
uv sync

# Run migrations
python pythonie/manage.py migrate --settings=pythonie.settings.dev
Expand Down
5 changes: 3 additions & 2 deletions DEVELOPMENT.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -168,7 +168,8 @@ python3.13 -m venv pythonie-venv
source pythonie-venv/bin/activate

# 2. Install dependencies
pip install -r requirements/dev.txt
pip install uv
uv sync

# 3. Migrate database
python pythonie/manage.py migrate --settings=pythonie.settings.dev
Expand DownExpand Up@@ -685,7 +686,7 @@ echo "django-debug-toolbar" >> requirements/main.in
uv pip compile requirements/main.in -o requirements/main.txt

# Install
pip install -r requirements/dev.txt
uv sync
```

### Database Migrations
Expand Down
13 changes: 5 additions & 8 deletions Dockerfile
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,16 +5,13 @@ RUN --mount=type=cache,target=/var/cache/apt \
apt install -y --no-install-recommends \
build-essential gcc neovim fish less iputils-ping postgresql-client \
ack
ADD requirements/main.txt \
requirements/dev.txt \
requirements/production.txt \
./requirements/

# Copy dependency specification files
COPY pyproject.toml uv.lock README.md ./

RUN --mount=type=cache,target=/root/.cache \
pip install -U pip uv ruff && \
python -m uv pip install \
-r requirements/main.txt \
-r requirements/dev.txt \
-r requirements/production.txt aws
uv sync --group production --no-install-project

FROM compile-stage AS tests-stage

4 changes: 2 additions & 2 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -56,7 +56,7 @@ If you prefer to develop without Docker:
3. Ensure you are running Python 3.13: `python -V` should output `Python 3.13.x`
4. Create a virtualenv: `python3 -m venv pythonie-venv`
5. Activate the virtualenv: `source pythonie-venv/bin/activate`
6. Install dependencies: `pip install -r requirements.txt` (or `uv pip install -r requirements.txt`)
6. Install uv and dependencies: `pip install uv && uv sync`
7. Set up the database: `python pythonie/manage.py migrate --settings=pythonie.settings.dev`
8. Generate sample data: `python pythonie/manage.py generate_sample_data --settings=pythonie.settings.dev`
9. Create a superuser: `python pythonie/manage.py createsuperuser --settings=pythonie.settings.dev`
Expand DownExpand Up@@ -259,7 +259,7 @@ This project uses several tools to streamline development:

### Import Errors or Module Not Found
- Rebuild Docker image: `task docker:build`
- Reinstall dependencies: `pip install -r requirements.txt`
- Reinstall dependencies: `uv sync`

## Contributing

Expand Down
47 changes: 27 additions & 20 deletions Taskfile.yaml
Original file line numberDiff line numberDiff line change
Expand Up@@ -135,40 +135,49 @@ tasks:
cmds:
- docker compose run --rm web python pythonie/manage.py collectstatic

dependencies:compute:
desc: Compute the dependencies
dependencies:lock:
desc: Update uv.lock file from pyproject.toml
cmds:
- toast deps:compute
- uv lock

dependencies:outdated:
desc: List the outdated dependencies
dependencies:upgrade:
desc: Upgrade all dependencies
cmds:
- toast deps:outdated
- uv lock --upgrade

dependencies:upgrade:
desc: Upgrade the dependencies
dependencies:sync:
desc: Install dependencies from lock file (development)
cmds:
- toast deps:upgrade
- uv sync

dependencies:upgrade:django:
desc: Upgrade Django to the latest compatible version
dependencies:sync:production:
desc: Install production dependencies only
cmds:
- toast deps:upgrade:django
- uv sync --no-dev --group production

dependencies:upgrade:wagtail:
desc: Upgrade Wagtail to the latest compatible version
dependencies:export:
desc: Export uv.lock to requirements.txt for Heroku
cmds:
- toast deps:upgrade:wagtail
- uv export --no-dev --group production -o requirements.txt
- uv export --group dev --group production -o requirements-dev.txt
- |
echo "# AUTO-GENERATED from pyproject.toml - DO NOT EDIT" | cat - requirements.txt > temp && mv temp requirements.txt
echo "# AUTO-GENERATED from pyproject.toml - DO NOT EDIT" | cat - requirements-dev.txt > temp && mv temp requirements-dev.txt

dependencies:outdated:
desc: List the outdated dependencies
cmds:
- toast deps:outdated

dependencies:security:
desc: Check dependencies for known security vulnerabilities
cmds:
- toast deps:security
- uv run pip-audit

dependencies:tree:
desc: Show the dependencies tree
cmds:
- toast deps:tree
- uv tree

docker:build:
desc: Build the docker image
Expand DownExpand Up@@ -213,9 +222,7 @@ tasks:
dependencies:upgrade:package:
desc: "Upgrade a specific package (usage: task dependencies:upgrade:package PACKAGE=django)"
cmds:
- python -m uv pip compile --upgrade-package $PACKAGE --output-file requirements/main.txt requirements/main.in
- python -m uv pip compile --upgrade-package $PACKAGE --output-file requirements/dev.txt requirements/dev.in
- python -m uv pip compile --upgrade-package $PACKAGE --output-file requirements/production.txt requirements/production.in
- uv lock --upgrade-package {{.PACKAGE}}

tests:
desc: Run all tests
Expand Down
135 changes: 135 additions & 0 deletions pyproject.toml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "pythonie"
version = "2025.12.23"
description = "Python Ireland website - Django/Wagtail CMS for python.ie and pycon.ie"
readme = "README.md"
requires-python = ">=3.13.0"
license = {text = "MIT"}
authors = [{name = "Python Ireland", email = "info@python.ie"}]
keywords = ["django", "wagtail", "cms", "python-ireland", "pycon"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Framework :: Django :: 5.2",
"Framework :: Wagtail :: 7",
"Programming Language :: Python :: 3.13",
"License :: OSI Approved :: MIT License",
]

# Main production dependencies (from requirements/main.in)
dependencies = [
"Delorean",
"Django>=5.2.0,<5.3", # Reste sur Django 5.2.x
"Willow",
"boto3",
"colander",
"defusedxml",
"dj-database-url",
"dj-static",
"django-compressor",
"django-extensions",
"django-libsass",
"django-modelcluster",
"django-storages",
"django-taggit",
"gunicorn",
"pandas",
"pydantic",
"python-dateutil",
"pytz",
"redis",
"requests>=2.32.5",
"wagtail>=7.2.0,<7.3", # Wagtail 7.2.x compatible avec Django 5.2
"whitenoise",
]

# PEP 735 Dependency Groups
[dependency-groups]
# Development dependencies (from requirements/dev.in)
dev = [
"coverage",
"django-debug-toolbar",
"factory-boy",
"fakeredis",
"isort",
"model_mommy",
"pip-audit",
"pipdeptree",
"ruff",
"uv",
]

# Production-specific dependencies (from requirements/production.in)
production = [
"psycopg[binary]",
]

# Tool configurations
[tool.ruff]
target-version = "py313"
line-length = 88
exclude = [
"migrations",
".venv",
"venv",
"pythonie-venv",
".git",
"__pycache__",
]

[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"F", # pyflakes
"I", # isort
"N", # pep8-naming
"W", # pycodestyle warnings
"UP", # pyupgrade
"DJ", # django-specific rules
]
ignore = [
"E501", # Line too long (handled by formatter)
]

[tool.ruff.lint.isort]
known-first-party = ["pythonie", "core", "meetups", "speakers", "sponsors"]
section-order = ["future", "standard-library", "third-party", "django", "wagtail", "first-party", "local-folder"]

[tool.ruff.lint.isort.sections]
"django" = ["django"]
"wagtail" = ["wagtail"]

[tool.ruff.format]
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false
line-ending = "auto"

[tool.coverage.run]
source = ["pythonie"]
omit = [
"*/migrations/*",
"*/tests/*",
"*/test_*.py",
"*/__pycache__/*",
"*/venv/*",
"*/.venv/*",
]

[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"def __repr__",
"raise AssertionError",
"raise NotImplementedError",
"if __name__ == .__main__.:",
]

[tool.django-stubs]
django_settings_module = "pythonie.settings.dev"

[tool.hatchling.build.targets.wheel]
packages = ["pythonie"]
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Draft
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
10 changes: 5 additions & 5 deletions .github/workflows/test.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,14 +9,14 @@ jobs:
DJANGO_SETTINGS_MODULE: pythonie.settings.tests
steps:
- uses: actions/checkout@v2
- name: Set Up Python 3.12
- name: Set Up Python 3.13
uses: actions/setup-python@v2
Comment on lines +12 to 13

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you consider setup-uv action instead of setup-python? It can install Python versions just fine, and yields a cleaner result in overall config in my experience.

with:
python-version: "3.12"
python-version: "3.13"
- name: Install the dependencies
run: |
python -m pip install --upgrade pip setuptools uv
python -m uv pip install -r requirements/main.txt -r requirements/dev.txt
python -m pip install --upgrade pip uv
uv sync
- name: Run the tests
run: |
python pythonie/manage.py test pythonie --verbosity=2
uv run python pythonie/manage.py test pythonie --verbosity=2
1 change: 1 addition & 0 deletions .tool-versions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
python 3.13.9
task 3.37.2
uv 0.9.18
57 changes: 46 additions & 11 deletions CLAUDE.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,7 +57,8 @@ Always specify settings module: `--settings=pythonie.settings.dev` (or `tests`,
# Setup
python3 -m venv pythonie-venv
source pythonie-venv/bin/activate
pip install -r requirements.txt
pip install uv
uv sync

# Database
python pythonie/manage.py migrate --settings=pythonie.settings.dev
Expand DownExpand Up@@ -128,32 +129,66 @@ task code:check

### Dependency Management

Uses `uv` for fast Python package management. Dependencies are defined in `.in` files and compiled to `.txt` files:
Uses `uv` with `pyproject.toml` for dependency management. Dependencies are defined in `pyproject.toml` and locked in `uv.lock`:

```bash
# Recompile all dependencies
task dependencies:compute
# or: toast deps:compute
**Structure:**
- `pyproject.toml` - Dependency specifications (edit this to add/remove dependencies)
- `uv.lock` - Locked versions (auto-generated, commit to git)
- `requirements.txt` - Auto-generated for Heroku deployment

# Check outdated packages
task dependencies:outdated
**Common Commands:**

```bash
# Update lock file after changing pyproject.toml
task dependencies:lock

# Upgrade all dependencies
task dependencies:upgrade

# Upgrade only Wagtail
task dependencies:upgrade:wagtail

# Upgrade specific package
task dependencies:upgrade:package PACKAGE=django

# Install dependencies (development)
task dependencies:sync

# Install production dependencies only
task dependencies:sync:production

# Generate requirements.txt for Heroku
task dependencies:export

# Check outdated packages
task dependencies:outdated

# Check for security vulnerabilities
task dependencies:security

# Show dependencies tree
task dependencies:tree
```

**Adding a New Dependency:**

1. Edit `pyproject.toml` to add the dependency:
```toml
dependencies = [
"new-package",
# ...
]
```

2. Update lock and generate requirements.txt:
```bash
task dependencies:lock
task dependencies:export
```

3. Commit both files:
```bash
git add pyproject.toml uv.lock requirements.txt
git commit -m "Add new-package dependency"
```

### Database Operations (Heroku)

```bash
Expand Down
3 changes: 2 additions & 1 deletion CONTRIBUTING.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -85,7 +85,8 @@ python3.13 -m venv pythonie-venv
source pythonie-venv/bin/activate

# Install dependencies
pip install -r requirements/dev.txt
pip install uv
uv sync

# Run migrations
python pythonie/manage.py migrate --settings=pythonie.settings.dev
Expand Down
5 changes: 3 additions & 2 deletions DEVELOPMENT.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -168,7 +168,8 @@ python3.13 -m venv pythonie-venv
source pythonie-venv/bin/activate

# 2. Install dependencies
pip install -r requirements/dev.txt
pip install uv
uv sync

# 3. Migrate database
python pythonie/manage.py migrate --settings=pythonie.settings.dev
Expand DownExpand Up@@ -685,7 +686,7 @@ echo "django-debug-toolbar" >> requirements/main.in
uv pip compile requirements/main.in -o requirements/main.txt

# Install
pip install -r requirements/dev.txt
uv sync
```

### Database Migrations
Expand Down
13 changes: 5 additions & 8 deletions Dockerfile
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,16 +5,13 @@ RUN --mount=type=cache,target=/var/cache/apt \
apt install -y --no-install-recommends \
build-essential gcc neovim fish less iputils-ping postgresql-client \
ack
ADD requirements/main.txt \
requirements/dev.txt \
requirements/production.txt \
./requirements/

# Copy dependency specification files
COPY pyproject.toml uv.lock README.md ./

RUN --mount=type=cache,target=/root/.cache \
pip install -U pip uv ruff && \
python -m uv pip install \
-r requirements/main.txt \
-r requirements/dev.txt \
-r requirements/production.txt aws
uv sync --group production --no-install-project

FROM compile-stage AS tests-stage

4 changes: 2 additions & 2 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -56,7 +56,7 @@ If you prefer to develop without Docker:
3. Ensure you are running Python 3.13: `python -V` should output `Python 3.13.x`
4. Create a virtualenv: `python3 -m venv pythonie-venv`
5. Activate the virtualenv: `source pythonie-venv/bin/activate`
6. Install dependencies: `pip install -r requirements.txt` (or `uv pip install -r requirements.txt`)
6. Install uv and dependencies: `pip install uv && uv sync`
7. Set up the database: `python pythonie/manage.py migrate --settings=pythonie.settings.dev`
8. Generate sample data: `python pythonie/manage.py generate_sample_data --settings=pythonie.settings.dev`
9. Create a superuser: `python pythonie/manage.py createsuperuser --settings=pythonie.settings.dev`
Expand DownExpand Up@@ -259,7 +259,7 @@ This project uses several tools to streamline development:

### Import Errors or Module Not Found
- Rebuild Docker image: `task docker:build`
- Reinstall dependencies: `pip install -r requirements.txt`
- Reinstall dependencies: `uv sync`

## Contributing

Expand Down
47 changes: 27 additions & 20 deletions Taskfile.yaml
Original file line numberDiff line numberDiff line change
Expand Up@@ -135,40 +135,49 @@ tasks:
cmds:
- docker compose run --rm web python pythonie/manage.py collectstatic

dependencies:compute:
desc: Compute the dependencies
dependencies:lock:
desc: Update uv.lock file from pyproject.toml
cmds:
- toast deps:compute
- uv lock

dependencies:outdated:
desc: List the outdated dependencies
dependencies:upgrade:
desc: Upgrade all dependencies
cmds:
- toast deps:outdated
- uv lock --upgrade

dependencies:upgrade:
desc: Upgrade the dependencies
dependencies:sync:
desc: Install dependencies from lock file (development)
cmds:
- toast deps:upgrade
- uv sync

dependencies:upgrade:django:
desc: Upgrade Django to the latest compatible version
dependencies:sync:production:
desc: Install production dependencies only
cmds:
- toast deps:upgrade:django
- uv sync --no-dev --group production

dependencies:upgrade:wagtail:
desc: Upgrade Wagtail to the latest compatible version
dependencies:export:
desc: Export uv.lock to requirements.txt for Heroku
cmds:
- toast deps:upgrade:wagtail
- uv export --no-dev --group production -o requirements.txt
- uv export --group dev --group production -o requirements-dev.txt
- |
echo "# AUTO-GENERATED from pyproject.toml - DO NOT EDIT" | cat - requirements.txt > temp && mv temp requirements.txt
echo "# AUTO-GENERATED from pyproject.toml - DO NOT EDIT" | cat - requirements-dev.txt > temp && mv temp requirements-dev.txt

dependencies:outdated:
desc: List the outdated dependencies
cmds:
- toast deps:outdated

dependencies:security:
desc: Check dependencies for known security vulnerabilities
cmds:
- toast deps:security
- uv run pip-audit

dependencies:tree:
desc: Show the dependencies tree
cmds:
- toast deps:tree
- uv tree

docker:build:
desc: Build the docker image
Expand DownExpand Up@@ -213,9 +222,7 @@ tasks:
dependencies:upgrade:package:
desc: "Upgrade a specific package (usage: task dependencies:upgrade:package PACKAGE=django)"
cmds:
- python -m uv pip compile --upgrade-package $PACKAGE --output-file requirements/main.txt requirements/main.in
- python -m uv pip compile --upgrade-package $PACKAGE --output-file requirements/dev.txt requirements/dev.in
- python -m uv pip compile --upgrade-package $PACKAGE --output-file requirements/production.txt requirements/production.in
- uv lock --upgrade-package {{.PACKAGE}}

tests:
desc: Run all tests
Expand Down
135 changes: 135 additions & 0 deletions pyproject.toml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "pythonie"
version = "2025.12.23"
description = "Python Ireland website - Django/Wagtail CMS for python.ie and pycon.ie"
readme = "README.md"
requires-python = ">=3.13.0"
license = {text = "MIT"}
authors = [{name = "Python Ireland", email = "info@python.ie"}]
keywords = ["django", "wagtail", "cms", "python-ireland", "pycon"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Framework :: Django :: 5.2",
"Framework :: Wagtail :: 7",
"Programming Language :: Python :: 3.13",
"License :: OSI Approved :: MIT License",
]

# Main production dependencies (from requirements/main.in)
dependencies = [
"Delorean",
"Django>=5.2.0,<5.3", # Reste sur Django 5.2.x
"Willow",
"boto3",
"colander",
"defusedxml",
"dj-database-url",
"dj-static",
"django-compressor",
"django-extensions",
"django-libsass",
"django-modelcluster",
"django-storages",
"django-taggit",
"gunicorn",
"pandas",
"pydantic",
"python-dateutil",
"pytz",
"redis",
"requests>=2.32.5",
"wagtail>=7.2.0,<7.3", # Wagtail 7.2.x compatible avec Django 5.2
"whitenoise",
]

# PEP 735 Dependency Groups
[dependency-groups]
# Development dependencies (from requirements/dev.in)
dev = [
"coverage",
"django-debug-toolbar",
"factory-boy",
"fakeredis",
"isort",
"model_mommy",
"pip-audit",
"pipdeptree",
"ruff",
"uv",
]

# Production-specific dependencies (from requirements/production.in)
production = [
"psycopg[binary]",
]

# Tool configurations
[tool.ruff]
target-version = "py313"
line-length = 88
exclude = [
"migrations",
".venv",
"venv",
"pythonie-venv",
".git",
"__pycache__",
]

[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"F", # pyflakes
"I", # isort
"N", # pep8-naming
"W", # pycodestyle warnings
"UP", # pyupgrade
"DJ", # django-specific rules
]
ignore = [
"E501", # Line too long (handled by formatter)
]

[tool.ruff.lint.isort]
known-first-party = ["pythonie", "core", "meetups", "speakers", "sponsors"]
section-order = ["future", "standard-library", "third-party", "django", "wagtail", "first-party", "local-folder"]

[tool.ruff.lint.isort.sections]
"django" = ["django"]
"wagtail" = ["wagtail"]

[tool.ruff.format]
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false
line-ending = "auto"

[tool.coverage.run]
source = ["pythonie"]
omit = [
"*/migrations/*",
"*/tests/*",
"*/test_*.py",
"*/__pycache__/*",
"*/venv/*",
"*/.venv/*",
]

[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"def __repr__",
"raise AssertionError",
"raise NotImplementedError",
"if __name__ == .__main__.:",
]

[tool.django-stubs]
django_settings_module = "pythonie.settings.dev"

[tool.hatchling.build.targets.wheel]
packages = ["pythonie"]
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Draft
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
10 changes: 5 additions & 5 deletions .github/workflows/test.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,14 +9,14 @@ jobs:
DJANGO_SETTINGS_MODULE: pythonie.settings.tests
steps:
- uses: actions/checkout@v2
- name: Set Up Python 3.12
- name: Set Up Python 3.13
uses: actions/setup-python@v2
Comment on lines +12 to 13

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you consider setup-uv action instead of setup-python? It can install Python versions just fine, and yields a cleaner result in overall config in my experience.

with:
python-version: "3.12"
python-version: "3.13"
- name: Install the dependencies
run: |
python -m pip install --upgrade pip setuptools uv
python -m uv pip install -r requirements/main.txt -r requirements/dev.txt
python -m pip install --upgrade pip uv
uv sync
- name: Run the tests
run: |
python pythonie/manage.py test pythonie --verbosity=2
uv run python pythonie/manage.py test pythonie --verbosity=2
1 change: 1 addition & 0 deletions .tool-versions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
python 3.13.9
task 3.37.2
uv 0.9.18
57 changes: 46 additions & 11 deletions CLAUDE.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,7 +57,8 @@ Always specify settings module: `--settings=pythonie.settings.dev` (or `tests`,
# Setup
python3 -m venv pythonie-venv
source pythonie-venv/bin/activate
pip install -r requirements.txt
pip install uv
uv sync

# Database
python pythonie/manage.py migrate --settings=pythonie.settings.dev
Expand DownExpand Up@@ -128,32 +129,66 @@ task code:check

### Dependency Management

Uses `uv` for fast Python package management. Dependencies are defined in `.in` files and compiled to `.txt` files:
Uses `uv` with `pyproject.toml` for dependency management. Dependencies are defined in `pyproject.toml` and locked in `uv.lock`:

```bash
# Recompile all dependencies
task dependencies:compute
# or: toast deps:compute
**Structure:**
- `pyproject.toml` - Dependency specifications (edit this to add/remove dependencies)
- `uv.lock` - Locked versions (auto-generated, commit to git)
- `requirements.txt` - Auto-generated for Heroku deployment

# Check outdated packages
task dependencies:outdated
**Common Commands:**

```bash
# Update lock file after changing pyproject.toml
task dependencies:lock

# Upgrade all dependencies
task dependencies:upgrade

# Upgrade only Wagtail
task dependencies:upgrade:wagtail

# Upgrade specific package
task dependencies:upgrade:package PACKAGE=django

# Install dependencies (development)
task dependencies:sync

# Install production dependencies only
task dependencies:sync:production

# Generate requirements.txt for Heroku
task dependencies:export

# Check outdated packages
task dependencies:outdated

# Check for security vulnerabilities
task dependencies:security

# Show dependencies tree
task dependencies:tree
```

**Adding a New Dependency:**

1. Edit `pyproject.toml` to add the dependency:
```toml
dependencies = [
"new-package",
# ...
]
```

2. Update lock and generate requirements.txt:
```bash
task dependencies:lock
task dependencies:export
```

3. Commit both files:
```bash
git add pyproject.toml uv.lock requirements.txt
git commit -m "Add new-package dependency"
```

### Database Operations (Heroku)

```bash
Expand Down
3 changes: 2 additions & 1 deletion CONTRIBUTING.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -85,7 +85,8 @@ python3.13 -m venv pythonie-venv
source pythonie-venv/bin/activate

# Install dependencies
pip install -r requirements/dev.txt
pip install uv
uv sync

# Run migrations
python pythonie/manage.py migrate --settings=pythonie.settings.dev
Expand Down
5 changes: 3 additions & 2 deletions DEVELOPMENT.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -168,7 +168,8 @@ python3.13 -m venv pythonie-venv
source pythonie-venv/bin/activate

# 2. Install dependencies
pip install -r requirements/dev.txt
pip install uv
uv sync

# 3. Migrate database
python pythonie/manage.py migrate --settings=pythonie.settings.dev
Expand DownExpand Up@@ -685,7 +686,7 @@ echo "django-debug-toolbar" >> requirements/main.in
uv pip compile requirements/main.in -o requirements/main.txt

# Install
pip install -r requirements/dev.txt
uv sync
```

### Database Migrations
Expand Down
13 changes: 5 additions & 8 deletions Dockerfile
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,16 +5,13 @@ RUN --mount=type=cache,target=/var/cache/apt \
apt install -y --no-install-recommends \
build-essential gcc neovim fish less iputils-ping postgresql-client \
ack
ADD requirements/main.txt \
requirements/dev.txt \
requirements/production.txt \
./requirements/

# Copy dependency specification files
COPY pyproject.toml uv.lock README.md ./

RUN --mount=type=cache,target=/root/.cache \
pip install -U pip uv ruff && \
python -m uv pip install \
-r requirements/main.txt \
-r requirements/dev.txt \
-r requirements/production.txt aws
uv sync --group production --no-install-project

FROM compile-stage AS tests-stage

4 changes: 2 additions & 2 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -56,7 +56,7 @@ If you prefer to develop without Docker:
3. Ensure you are running Python 3.13: `python -V` should output `Python 3.13.x`
4. Create a virtualenv: `python3 -m venv pythonie-venv`
5. Activate the virtualenv: `source pythonie-venv/bin/activate`
6. Install dependencies: `pip install -r requirements.txt` (or `uv pip install -r requirements.txt`)
6. Install uv and dependencies: `pip install uv && uv sync`
7. Set up the database: `python pythonie/manage.py migrate --settings=pythonie.settings.dev`
8. Generate sample data: `python pythonie/manage.py generate_sample_data --settings=pythonie.settings.dev`
9. Create a superuser: `python pythonie/manage.py createsuperuser --settings=pythonie.settings.dev`
Expand DownExpand Up@@ -259,7 +259,7 @@ This project uses several tools to streamline development:

### Import Errors or Module Not Found
- Rebuild Docker image: `task docker:build`
- Reinstall dependencies: `pip install -r requirements.txt`
- Reinstall dependencies: `uv sync`

## Contributing

Expand Down
47 changes: 27 additions & 20 deletions Taskfile.yaml
Original file line numberDiff line numberDiff line change
Expand Up@@ -135,40 +135,49 @@ tasks:
cmds:
- docker compose run --rm web python pythonie/manage.py collectstatic

dependencies:compute:
desc: Compute the dependencies
dependencies:lock:
desc: Update uv.lock file from pyproject.toml
cmds:
- toast deps:compute
- uv lock

dependencies:outdated:
desc: List the outdated dependencies
dependencies:upgrade:
desc: Upgrade all dependencies
cmds:
- toast deps:outdated
- uv lock --upgrade

dependencies:upgrade:
desc: Upgrade the dependencies
dependencies:sync:
desc: Install dependencies from lock file (development)
cmds:
- toast deps:upgrade
- uv sync

dependencies:upgrade:django:
desc: Upgrade Django to the latest compatible version
dependencies:sync:production:
desc: Install production dependencies only
cmds:
- toast deps:upgrade:django
- uv sync --no-dev --group production

dependencies:upgrade:wagtail:
desc: Upgrade Wagtail to the latest compatible version
dependencies:export:
desc: Export uv.lock to requirements.txt for Heroku
cmds:
- toast deps:upgrade:wagtail
- uv export --no-dev --group production -o requirements.txt
- uv export --group dev --group production -o requirements-dev.txt
- |
echo "# AUTO-GENERATED from pyproject.toml - DO NOT EDIT" | cat - requirements.txt > temp && mv temp requirements.txt
echo "# AUTO-GENERATED from pyproject.toml - DO NOT EDIT" | cat - requirements-dev.txt > temp && mv temp requirements-dev.txt

dependencies:outdated:
desc: List the outdated dependencies
cmds:
- toast deps:outdated

dependencies:security:
desc: Check dependencies for known security vulnerabilities
cmds:
- toast deps:security
- uv run pip-audit

dependencies:tree:
desc: Show the dependencies tree
cmds:
- toast deps:tree
- uv tree

docker:build:
desc: Build the docker image
Expand DownExpand Up@@ -213,9 +222,7 @@ tasks:
dependencies:upgrade:package:
desc: "Upgrade a specific package (usage: task dependencies:upgrade:package PACKAGE=django)"
cmds:
- python -m uv pip compile --upgrade-package $PACKAGE --output-file requirements/main.txt requirements/main.in
- python -m uv pip compile --upgrade-package $PACKAGE --output-file requirements/dev.txt requirements/dev.in
- python -m uv pip compile --upgrade-package $PACKAGE --output-file requirements/production.txt requirements/production.in
- uv lock --upgrade-package {{.PACKAGE}}

tests:
desc: Run all tests
Expand Down
135 changes: 135 additions & 0 deletions pyproject.toml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "pythonie"
version = "2025.12.23"
description = "Python Ireland website - Django/Wagtail CMS for python.ie and pycon.ie"
readme = "README.md"
requires-python = ">=3.13.0"
license = {text = "MIT"}
authors = [{name = "Python Ireland", email = "info@python.ie"}]
keywords = ["django", "wagtail", "cms", "python-ireland", "pycon"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Framework :: Django :: 5.2",
"Framework :: Wagtail :: 7",
"Programming Language :: Python :: 3.13",
"License :: OSI Approved :: MIT License",
]

# Main production dependencies (from requirements/main.in)
dependencies = [
"Delorean",
"Django>=5.2.0,<5.3", # Reste sur Django 5.2.x
"Willow",
"boto3",
"colander",
"defusedxml",
"dj-database-url",
"dj-static",
"django-compressor",
"django-extensions",
"django-libsass",
"django-modelcluster",
"django-storages",
"django-taggit",
"gunicorn",
"pandas",
"pydantic",
"python-dateutil",
"pytz",
"redis",
"requests>=2.32.5",
"wagtail>=7.2.0,<7.3", # Wagtail 7.2.x compatible avec Django 5.2
"whitenoise",
]

# PEP 735 Dependency Groups
[dependency-groups]
# Development dependencies (from requirements/dev.in)
dev = [
"coverage",
"django-debug-toolbar",
"factory-boy",
"fakeredis",
"isort",
"model_mommy",
"pip-audit",
"pipdeptree",
"ruff",
"uv",
]

# Production-specific dependencies (from requirements/production.in)
production = [
"psycopg[binary]",
]

# Tool configurations
[tool.ruff]
target-version = "py313"
line-length = 88
exclude = [
"migrations",
".venv",
"venv",
"pythonie-venv",
".git",
"__pycache__",
]

[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"F", # pyflakes
"I", # isort
"N", # pep8-naming
"W", # pycodestyle warnings
"UP", # pyupgrade
"DJ", # django-specific rules
]
ignore = [
"E501", # Line too long (handled by formatter)
]

[tool.ruff.lint.isort]
known-first-party = ["pythonie", "core", "meetups", "speakers", "sponsors"]
section-order = ["future", "standard-library", "third-party", "django", "wagtail", "first-party", "local-folder"]

[tool.ruff.lint.isort.sections]
"django" = ["django"]
"wagtail" = ["wagtail"]

[tool.ruff.format]
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false
line-ending = "auto"

[tool.coverage.run]
source = ["pythonie"]
omit = [
"*/migrations/*",
"*/tests/*",
"*/test_*.py",
"*/__pycache__/*",
"*/venv/*",
"*/.venv/*",
]

[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"def __repr__",
"raise AssertionError",
"raise NotImplementedError",
"if __name__ == .__main__.:",
]

[tool.django-stubs]
django_settings_module = "pythonie.settings.dev"

[tool.hatchling.build.targets.wheel]
packages = ["pythonie"]
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Draft
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
10 changes: 5 additions & 5 deletions .github/workflows/test.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,14 +9,14 @@ jobs:
DJANGO_SETTINGS_MODULE: pythonie.settings.tests
steps:
- uses: actions/checkout@v2
- name: Set Up Python 3.12
- name: Set Up Python 3.13
uses: actions/setup-python@v2
Comment on lines +12 to 13

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you consider setup-uv action instead of setup-python? It can install Python versions just fine, and yields a cleaner result in overall config in my experience.

with:
python-version: "3.12"
python-version: "3.13"
- name: Install the dependencies
run: |
python -m pip install --upgrade pip setuptools uv
python -m uv pip install -r requirements/main.txt -r requirements/dev.txt
python -m pip install --upgrade pip uv
uv sync
- name: Run the tests
run: |
python pythonie/manage.py test pythonie --verbosity=2
uv run python pythonie/manage.py test pythonie --verbosity=2
1 change: 1 addition & 0 deletions .tool-versions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
python 3.13.9
task 3.37.2
uv 0.9.18
57 changes: 46 additions & 11 deletions CLAUDE.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,7 +57,8 @@ Always specify settings module: `--settings=pythonie.settings.dev` (or `tests`,
# Setup
python3 -m venv pythonie-venv
source pythonie-venv/bin/activate
pip install -r requirements.txt
pip install uv
uv sync

# Database
python pythonie/manage.py migrate --settings=pythonie.settings.dev
Expand DownExpand Up@@ -128,32 +129,66 @@ task code:check

### Dependency Management

Uses `uv` for fast Python package management. Dependencies are defined in `.in` files and compiled to `.txt` files:
Uses `uv` with `pyproject.toml` for dependency management. Dependencies are defined in `pyproject.toml` and locked in `uv.lock`:

```bash
# Recompile all dependencies
task dependencies:compute
# or: toast deps:compute
**Structure:**
- `pyproject.toml` - Dependency specifications (edit this to add/remove dependencies)
- `uv.lock` - Locked versions (auto-generated, commit to git)
- `requirements.txt` - Auto-generated for Heroku deployment

# Check outdated packages
task dependencies:outdated
**Common Commands:**

```bash
# Update lock file after changing pyproject.toml
task dependencies:lock

# Upgrade all dependencies
task dependencies:upgrade

# Upgrade only Wagtail
task dependencies:upgrade:wagtail

# Upgrade specific package
task dependencies:upgrade:package PACKAGE=django

# Install dependencies (development)
task dependencies:sync

# Install production dependencies only
task dependencies:sync:production

# Generate requirements.txt for Heroku
task dependencies:export

# Check outdated packages
task dependencies:outdated

# Check for security vulnerabilities
task dependencies:security

# Show dependencies tree
task dependencies:tree
```

**Adding a New Dependency:**

1. Edit `pyproject.toml` to add the dependency:
```toml
dependencies = [
"new-package",
# ...
]
```

2. Update lock and generate requirements.txt:
```bash
task dependencies:lock
task dependencies:export
```

3. Commit both files:
```bash
git add pyproject.toml uv.lock requirements.txt
git commit -m "Add new-package dependency"
```

### Database Operations (Heroku)

```bash
Expand Down
3 changes: 2 additions & 1 deletion CONTRIBUTING.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -85,7 +85,8 @@ python3.13 -m venv pythonie-venv
source pythonie-venv/bin/activate

# Install dependencies
pip install -r requirements/dev.txt
pip install uv
uv sync

# Run migrations
python pythonie/manage.py migrate --settings=pythonie.settings.dev
Expand Down
5 changes: 3 additions & 2 deletions DEVELOPMENT.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -168,7 +168,8 @@ python3.13 -m venv pythonie-venv
source pythonie-venv/bin/activate

# 2. Install dependencies
pip install -r requirements/dev.txt
pip install uv
uv sync

# 3. Migrate database
python pythonie/manage.py migrate --settings=pythonie.settings.dev
Expand DownExpand Up@@ -685,7 +686,7 @@ echo "django-debug-toolbar" >> requirements/main.in
uv pip compile requirements/main.in -o requirements/main.txt

# Install
pip install -r requirements/dev.txt
uv sync
```

### Database Migrations
Expand Down
13 changes: 5 additions & 8 deletions Dockerfile
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,16 +5,13 @@ RUN --mount=type=cache,target=/var/cache/apt \
apt install -y --no-install-recommends \
build-essential gcc neovim fish less iputils-ping postgresql-client \
ack
ADD requirements/main.txt \
requirements/dev.txt \
requirements/production.txt \
./requirements/

# Copy dependency specification files
COPY pyproject.toml uv.lock README.md ./

RUN --mount=type=cache,target=/root/.cache \
pip install -U pip uv ruff && \
python -m uv pip install \
-r requirements/main.txt \
-r requirements/dev.txt \
-r requirements/production.txt aws
uv sync --group production --no-install-project

FROM compile-stage AS tests-stage

4 changes: 2 additions & 2 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -56,7 +56,7 @@ If you prefer to develop without Docker:
3. Ensure you are running Python 3.13: `python -V` should output `Python 3.13.x`
4. Create a virtualenv: `python3 -m venv pythonie-venv`
5. Activate the virtualenv: `source pythonie-venv/bin/activate`
6. Install dependencies: `pip install -r requirements.txt` (or `uv pip install -r requirements.txt`)
6. Install uv and dependencies: `pip install uv && uv sync`
7. Set up the database: `python pythonie/manage.py migrate --settings=pythonie.settings.dev`
8. Generate sample data: `python pythonie/manage.py generate_sample_data --settings=pythonie.settings.dev`
9. Create a superuser: `python pythonie/manage.py createsuperuser --settings=pythonie.settings.dev`
Expand DownExpand Up@@ -259,7 +259,7 @@ This project uses several tools to streamline development:

### Import Errors or Module Not Found
- Rebuild Docker image: `task docker:build`
- Reinstall dependencies: `pip install -r requirements.txt`
- Reinstall dependencies: `uv sync`

## Contributing

Expand Down
47 changes: 27 additions & 20 deletions Taskfile.yaml
Original file line numberDiff line numberDiff line change
Expand Up@@ -135,40 +135,49 @@ tasks:
cmds:
- docker compose run --rm web python pythonie/manage.py collectstatic

dependencies:compute:
desc: Compute the dependencies
dependencies:lock:
desc: Update uv.lock file from pyproject.toml
cmds:
- toast deps:compute
- uv lock

dependencies:outdated:
desc: List the outdated dependencies
dependencies:upgrade:
desc: Upgrade all dependencies
cmds:
- toast deps:outdated
- uv lock --upgrade

dependencies:upgrade:
desc: Upgrade the dependencies
dependencies:sync:
desc: Install dependencies from lock file (development)
cmds:
- toast deps:upgrade
- uv sync

dependencies:upgrade:django:
desc: Upgrade Django to the latest compatible version
dependencies:sync:production:
desc: Install production dependencies only
cmds:
- toast deps:upgrade:django
- uv sync --no-dev --group production

dependencies:upgrade:wagtail:
desc: Upgrade Wagtail to the latest compatible version
dependencies:export:
desc: Export uv.lock to requirements.txt for Heroku
cmds:
- toast deps:upgrade:wagtail
- uv export --no-dev --group production -o requirements.txt
- uv export --group dev --group production -o requirements-dev.txt
- |
echo "# AUTO-GENERATED from pyproject.toml - DO NOT EDIT" | cat - requirements.txt > temp && mv temp requirements.txt
echo "# AUTO-GENERATED from pyproject.toml - DO NOT EDIT" | cat - requirements-dev.txt > temp && mv temp requirements-dev.txt

dependencies:outdated:
desc: List the outdated dependencies
cmds:
- toast deps:outdated

dependencies:security:
desc: Check dependencies for known security vulnerabilities
cmds:
- toast deps:security
- uv run pip-audit

dependencies:tree:
desc: Show the dependencies tree
cmds:
- toast deps:tree
- uv tree

docker:build:
desc: Build the docker image
Expand DownExpand Up@@ -213,9 +222,7 @@ tasks:
dependencies:upgrade:package:
desc: "Upgrade a specific package (usage: task dependencies:upgrade:package PACKAGE=django)"
cmds:
- python -m uv pip compile --upgrade-package $PACKAGE --output-file requirements/main.txt requirements/main.in
- python -m uv pip compile --upgrade-package $PACKAGE --output-file requirements/dev.txt requirements/dev.in
- python -m uv pip compile --upgrade-package $PACKAGE --output-file requirements/production.txt requirements/production.in
- uv lock --upgrade-package {{.PACKAGE}}

tests:
desc: Run all tests
Expand Down
135 changes: 135 additions & 0 deletions pyproject.toml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "pythonie"
version = "2025.12.23"
description = "Python Ireland website - Django/Wagtail CMS for python.ie and pycon.ie"
readme = "README.md"
requires-python = ">=3.13.0"
license = {text = "MIT"}
authors = [{name = "Python Ireland", email = "info@python.ie"}]
keywords = ["django", "wagtail", "cms", "python-ireland", "pycon"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Framework :: Django :: 5.2",
"Framework :: Wagtail :: 7",
"Programming Language :: Python :: 3.13",
"License :: OSI Approved :: MIT License",
]

# Main production dependencies (from requirements/main.in)
dependencies = [
"Delorean",
"Django>=5.2.0,<5.3", # Reste sur Django 5.2.x
"Willow",
"boto3",
"colander",
"defusedxml",
"dj-database-url",
"dj-static",
"django-compressor",
"django-extensions",
"django-libsass",
"django-modelcluster",
"django-storages",
"django-taggit",
"gunicorn",
"pandas",
"pydantic",
"python-dateutil",
"pytz",
"redis",
"requests>=2.32.5",
"wagtail>=7.2.0,<7.3", # Wagtail 7.2.x compatible avec Django 5.2
"whitenoise",
]

# PEP 735 Dependency Groups
[dependency-groups]
# Development dependencies (from requirements/dev.in)
dev = [
"coverage",
"django-debug-toolbar",
"factory-boy",
"fakeredis",
"isort",
"model_mommy",
"pip-audit",
"pipdeptree",
"ruff",
"uv",
]

# Production-specific dependencies (from requirements/production.in)
production = [
"psycopg[binary]",
]

# Tool configurations
[tool.ruff]
target-version = "py313"
line-length = 88
exclude = [
"migrations",
".venv",
"venv",
"pythonie-venv",
".git",
"__pycache__",
]

[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"F", # pyflakes
"I", # isort
"N", # pep8-naming
"W", # pycodestyle warnings
"UP", # pyupgrade
"DJ", # django-specific rules
]
ignore = [
"E501", # Line too long (handled by formatter)
]

[tool.ruff.lint.isort]
known-first-party = ["pythonie", "core", "meetups", "speakers", "sponsors"]
section-order = ["future", "standard-library", "third-party", "django", "wagtail", "first-party", "local-folder"]

[tool.ruff.lint.isort.sections]
"django" = ["django"]
"wagtail" = ["wagtail"]

[tool.ruff.format]
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false
line-ending = "auto"

[tool.coverage.run]
source = ["pythonie"]
omit = [
"*/migrations/*",
"*/tests/*",
"*/test_*.py",
"*/__pycache__/*",
"*/venv/*",
"*/.venv/*",
]

[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"def __repr__",
"raise AssertionError",
"raise NotImplementedError",
"if __name__ == .__main__.:",
]

[tool.django-stubs]
django_settings_module = "pythonie.settings.dev"

[tool.hatchling.build.targets.wheel]
packages = ["pythonie"]
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Draft
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
10 changes: 5 additions & 5 deletions .github/workflows/test.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,14 +9,14 @@ jobs:
DJANGO_SETTINGS_MODULE: pythonie.settings.tests
steps:
- uses: actions/checkout@v2
- name: Set Up Python 3.12
- name: Set Up Python 3.13
uses: actions/setup-python@v2
Comment on lines +12 to 13

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you consider setup-uv action instead of setup-python? It can install Python versions just fine, and yields a cleaner result in overall config in my experience.

with:
python-version: "3.12"
python-version: "3.13"
- name: Install the dependencies
run: |
python -m pip install --upgrade pip setuptools uv
python -m uv pip install -r requirements/main.txt -r requirements/dev.txt
python -m pip install --upgrade pip uv
uv sync
- name: Run the tests
run: |
python pythonie/manage.py test pythonie --verbosity=2
uv run python pythonie/manage.py test pythonie --verbosity=2
1 change: 1 addition & 0 deletions .tool-versions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
python 3.13.9
task 3.37.2
uv 0.9.18
57 changes: 46 additions & 11 deletions CLAUDE.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,7 +57,8 @@ Always specify settings module: `--settings=pythonie.settings.dev` (or `tests`,
# Setup
python3 -m venv pythonie-venv
source pythonie-venv/bin/activate
pip install -r requirements.txt
pip install uv
uv sync

# Database
python pythonie/manage.py migrate --settings=pythonie.settings.dev
Expand DownExpand Up@@ -128,32 +129,66 @@ task code:check

### Dependency Management

Uses `uv` for fast Python package management. Dependencies are defined in `.in` files and compiled to `.txt` files:
Uses `uv` with `pyproject.toml` for dependency management. Dependencies are defined in `pyproject.toml` and locked in `uv.lock`:

```bash
# Recompile all dependencies
task dependencies:compute
# or: toast deps:compute
**Structure:**
- `pyproject.toml` - Dependency specifications (edit this to add/remove dependencies)
- `uv.lock` - Locked versions (auto-generated, commit to git)
- `requirements.txt` - Auto-generated for Heroku deployment

# Check outdated packages
task dependencies:outdated
**Common Commands:**

```bash
# Update lock file after changing pyproject.toml
task dependencies:lock

# Upgrade all dependencies
task dependencies:upgrade

# Upgrade only Wagtail
task dependencies:upgrade:wagtail

# Upgrade specific package
task dependencies:upgrade:package PACKAGE=django

# Install dependencies (development)
task dependencies:sync

# Install production dependencies only
task dependencies:sync:production

# Generate requirements.txt for Heroku
task dependencies:export

# Check outdated packages
task dependencies:outdated

# Check for security vulnerabilities
task dependencies:security

# Show dependencies tree
task dependencies:tree
```

**Adding a New Dependency:**

1. Edit `pyproject.toml` to add the dependency:
```toml
dependencies = [
"new-package",
# ...
]
```

2. Update lock and generate requirements.txt:
```bash
task dependencies:lock
task dependencies:export
```

3. Commit both files:
```bash
git add pyproject.toml uv.lock requirements.txt
git commit -m "Add new-package dependency"
```

### Database Operations (Heroku)

```bash
Expand Down
3 changes: 2 additions & 1 deletion CONTRIBUTING.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -85,7 +85,8 @@ python3.13 -m venv pythonie-venv
source pythonie-venv/bin/activate

# Install dependencies
pip install -r requirements/dev.txt
pip install uv
uv sync

# Run migrations
python pythonie/manage.py migrate --settings=pythonie.settings.dev
Expand Down
5 changes: 3 additions & 2 deletions DEVELOPMENT.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -168,7 +168,8 @@ python3.13 -m venv pythonie-venv
source pythonie-venv/bin/activate

# 2. Install dependencies
pip install -r requirements/dev.txt
pip install uv
uv sync

# 3. Migrate database
python pythonie/manage.py migrate --settings=pythonie.settings.dev
Expand DownExpand Up@@ -685,7 +686,7 @@ echo "django-debug-toolbar" >> requirements/main.in
uv pip compile requirements/main.in -o requirements/main.txt

# Install
pip install -r requirements/dev.txt
uv sync
```

### Database Migrations
Expand Down
13 changes: 5 additions & 8 deletions Dockerfile
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,16 +5,13 @@ RUN --mount=type=cache,target=/var/cache/apt \
apt install -y --no-install-recommends \
build-essential gcc neovim fish less iputils-ping postgresql-client \
ack
ADD requirements/main.txt \
requirements/dev.txt \
requirements/production.txt \
./requirements/

# Copy dependency specification files
COPY pyproject.toml uv.lock README.md ./

RUN --mount=type=cache,target=/root/.cache \
pip install -U pip uv ruff && \
python -m uv pip install \
-r requirements/main.txt \
-r requirements/dev.txt \
-r requirements/production.txt aws
uv sync --group production --no-install-project

FROM compile-stage AS tests-stage

4 changes: 2 additions & 2 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -56,7 +56,7 @@ If you prefer to develop without Docker:
3. Ensure you are running Python 3.13: `python -V` should output `Python 3.13.x`
4. Create a virtualenv: `python3 -m venv pythonie-venv`
5. Activate the virtualenv: `source pythonie-venv/bin/activate`
6. Install dependencies: `pip install -r requirements.txt` (or `uv pip install -r requirements.txt`)
6. Install uv and dependencies: `pip install uv && uv sync`
7. Set up the database: `python pythonie/manage.py migrate --settings=pythonie.settings.dev`
8. Generate sample data: `python pythonie/manage.py generate_sample_data --settings=pythonie.settings.dev`
9. Create a superuser: `python pythonie/manage.py createsuperuser --settings=pythonie.settings.dev`
Expand DownExpand Up@@ -259,7 +259,7 @@ This project uses several tools to streamline development:

### Import Errors or Module Not Found
- Rebuild Docker image: `task docker:build`
- Reinstall dependencies: `pip install -r requirements.txt`
- Reinstall dependencies: `uv sync`

## Contributing

Expand Down
47 changes: 27 additions & 20 deletions Taskfile.yaml
Original file line numberDiff line numberDiff line change
Expand Up@@ -135,40 +135,49 @@ tasks:
cmds:
- docker compose run --rm web python pythonie/manage.py collectstatic

dependencies:compute:
desc: Compute the dependencies
dependencies:lock:
desc: Update uv.lock file from pyproject.toml
cmds:
- toast deps:compute
- uv lock

dependencies:outdated:
desc: List the outdated dependencies
dependencies:upgrade:
desc: Upgrade all dependencies
cmds:
- toast deps:outdated
- uv lock --upgrade

dependencies:upgrade:
desc: Upgrade the dependencies
dependencies:sync:
desc: Install dependencies from lock file (development)
cmds:
- toast deps:upgrade
- uv sync

dependencies:upgrade:django:
desc: Upgrade Django to the latest compatible version
dependencies:sync:production:
desc: Install production dependencies only
cmds:
- toast deps:upgrade:django
- uv sync --no-dev --group production

dependencies:upgrade:wagtail:
desc: Upgrade Wagtail to the latest compatible version
dependencies:export:
desc: Export uv.lock to requirements.txt for Heroku
cmds:
- toast deps:upgrade:wagtail
- uv export --no-dev --group production -o requirements.txt
- uv export --group dev --group production -o requirements-dev.txt
- |
echo "# AUTO-GENERATED from pyproject.toml - DO NOT EDIT" | cat - requirements.txt > temp && mv temp requirements.txt
echo "# AUTO-GENERATED from pyproject.toml - DO NOT EDIT" | cat - requirements-dev.txt > temp && mv temp requirements-dev.txt

dependencies:outdated:
desc: List the outdated dependencies
cmds:
- toast deps:outdated

dependencies:security:
desc: Check dependencies for known security vulnerabilities
cmds:
- toast deps:security
- uv run pip-audit

dependencies:tree:
desc: Show the dependencies tree
cmds:
- toast deps:tree
- uv tree

docker:build:
desc: Build the docker image
Expand DownExpand Up@@ -213,9 +222,7 @@ tasks:
dependencies:upgrade:package:
desc: "Upgrade a specific package (usage: task dependencies:upgrade:package PACKAGE=django)"
cmds:
- python -m uv pip compile --upgrade-package $PACKAGE --output-file requirements/main.txt requirements/main.in
- python -m uv pip compile --upgrade-package $PACKAGE --output-file requirements/dev.txt requirements/dev.in
- python -m uv pip compile --upgrade-package $PACKAGE --output-file requirements/production.txt requirements/production.in
- uv lock --upgrade-package {{.PACKAGE}}

tests:
desc: Run all tests
Expand Down
135 changes: 135 additions & 0 deletions pyproject.toml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "pythonie"
version = "2025.12.23"
description = "Python Ireland website - Django/Wagtail CMS for python.ie and pycon.ie"
readme = "README.md"
requires-python = ">=3.13.0"
license = {text = "MIT"}
authors = [{name = "Python Ireland", email = "info@python.ie"}]
keywords = ["django", "wagtail", "cms", "python-ireland", "pycon"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Framework :: Django :: 5.2",
"Framework :: Wagtail :: 7",
"Programming Language :: Python :: 3.13",
"License :: OSI Approved :: MIT License",
]

# Main production dependencies (from requirements/main.in)
dependencies = [
"Delorean",
"Django>=5.2.0,<5.3", # Reste sur Django 5.2.x
"Willow",
"boto3",
"colander",
"defusedxml",
"dj-database-url",
"dj-static",
"django-compressor",
"django-extensions",
"django-libsass",
"django-modelcluster",
"django-storages",
"django-taggit",
"gunicorn",
"pandas",
"pydantic",
"python-dateutil",
"pytz",
"redis",
"requests>=2.32.5",
"wagtail>=7.2.0,<7.3", # Wagtail 7.2.x compatible avec Django 5.2
"whitenoise",
]

# PEP 735 Dependency Groups
[dependency-groups]
# Development dependencies (from requirements/dev.in)
dev = [
"coverage",
"django-debug-toolbar",
"factory-boy",
"fakeredis",
"isort",
"model_mommy",
"pip-audit",
"pipdeptree",
"ruff",
"uv",
]

# Production-specific dependencies (from requirements/production.in)
production = [
"psycopg[binary]",
]

# Tool configurations
[tool.ruff]
target-version = "py313"
line-length = 88
exclude = [
"migrations",
".venv",
"venv",
"pythonie-venv",
".git",
"__pycache__",
]

[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"F", # pyflakes
"I", # isort
"N", # pep8-naming
"W", # pycodestyle warnings
"UP", # pyupgrade
"DJ", # django-specific rules
]
ignore = [
"E501", # Line too long (handled by formatter)
]

[tool.ruff.lint.isort]
known-first-party = ["pythonie", "core", "meetups", "speakers", "sponsors"]
section-order = ["future", "standard-library", "third-party", "django", "wagtail", "first-party", "local-folder"]

[tool.ruff.lint.isort.sections]
"django" = ["django"]
"wagtail" = ["wagtail"]

[tool.ruff.format]
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false
line-ending = "auto"

[tool.coverage.run]
source = ["pythonie"]
omit = [
"*/migrations/*",
"*/tests/*",
"*/test_*.py",
"*/__pycache__/*",
"*/venv/*",
"*/.venv/*",
]

[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"def __repr__",
"raise AssertionError",
"raise NotImplementedError",
"if __name__ == .__main__.:",
]

[tool.django-stubs]
django_settings_module = "pythonie.settings.dev"

[tool.hatchling.build.targets.wheel]
packages = ["pythonie"]
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Draft
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
10 changes: 5 additions & 5 deletions .github/workflows/test.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,14 +9,14 @@ jobs:
DJANGO_SETTINGS_MODULE: pythonie.settings.tests
steps:
- uses: actions/checkout@v2
- name: Set Up Python 3.12
- name: Set Up Python 3.13
uses: actions/setup-python@v2
Comment on lines +12 to 13

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you consider setup-uv action instead of setup-python? It can install Python versions just fine, and yields a cleaner result in overall config in my experience.

with:
python-version: "3.12"
python-version: "3.13"
- name: Install the dependencies
run: |
python -m pip install --upgrade pip setuptools uv
python -m uv pip install -r requirements/main.txt -r requirements/dev.txt
python -m pip install --upgrade pip uv
uv sync
- name: Run the tests
run: |
python pythonie/manage.py test pythonie --verbosity=2
uv run python pythonie/manage.py test pythonie --verbosity=2
1 change: 1 addition & 0 deletions .tool-versions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
python 3.13.9
task 3.37.2
uv 0.9.18
57 changes: 46 additions & 11 deletions CLAUDE.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,7 +57,8 @@ Always specify settings module: `--settings=pythonie.settings.dev` (or `tests`,
# Setup
python3 -m venv pythonie-venv
source pythonie-venv/bin/activate
pip install -r requirements.txt
pip install uv
uv sync

# Database
python pythonie/manage.py migrate --settings=pythonie.settings.dev
Expand DownExpand Up@@ -128,32 +129,66 @@ task code:check

### Dependency Management

Uses `uv` for fast Python package management. Dependencies are defined in `.in` files and compiled to `.txt` files:
Uses `uv` with `pyproject.toml` for dependency management. Dependencies are defined in `pyproject.toml` and locked in `uv.lock`:

```bash
# Recompile all dependencies
task dependencies:compute
# or: toast deps:compute
**Structure:**
- `pyproject.toml` - Dependency specifications (edit this to add/remove dependencies)
- `uv.lock` - Locked versions (auto-generated, commit to git)
- `requirements.txt` - Auto-generated for Heroku deployment

# Check outdated packages
task dependencies:outdated
**Common Commands:**

```bash
# Update lock file after changing pyproject.toml
task dependencies:lock

# Upgrade all dependencies
task dependencies:upgrade

# Upgrade only Wagtail
task dependencies:upgrade:wagtail

# Upgrade specific package
task dependencies:upgrade:package PACKAGE=django

# Install dependencies (development)
task dependencies:sync

# Install production dependencies only
task dependencies:sync:production

# Generate requirements.txt for Heroku
task dependencies:export

# Check outdated packages
task dependencies:outdated

# Check for security vulnerabilities
task dependencies:security

# Show dependencies tree
task dependencies:tree
```

**Adding a New Dependency:**

1. Edit `pyproject.toml` to add the dependency:
```toml
dependencies = [
"new-package",
# ...
]
```

2. Update lock and generate requirements.txt:
```bash
task dependencies:lock
task dependencies:export
```

3. Commit both files:
```bash
git add pyproject.toml uv.lock requirements.txt
git commit -m "Add new-package dependency"
```

### Database Operations (Heroku)

```bash
Expand Down
3 changes: 2 additions & 1 deletion CONTRIBUTING.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -85,7 +85,8 @@ python3.13 -m venv pythonie-venv
source pythonie-venv/bin/activate

# Install dependencies
pip install -r requirements/dev.txt
pip install uv
uv sync

# Run migrations
python pythonie/manage.py migrate --settings=pythonie.settings.dev
Expand Down
5 changes: 3 additions & 2 deletions DEVELOPMENT.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -168,7 +168,8 @@ python3.13 -m venv pythonie-venv
source pythonie-venv/bin/activate

# 2. Install dependencies
pip install -r requirements/dev.txt
pip install uv
uv sync

# 3. Migrate database
python pythonie/manage.py migrate --settings=pythonie.settings.dev
Expand DownExpand Up@@ -685,7 +686,7 @@ echo "django-debug-toolbar" >> requirements/main.in
uv pip compile requirements/main.in -o requirements/main.txt

# Install
pip install -r requirements/dev.txt
uv sync
```

### Database Migrations
Expand Down
13 changes: 5 additions & 8 deletions Dockerfile
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,16 +5,13 @@ RUN --mount=type=cache,target=/var/cache/apt \
apt install -y --no-install-recommends \
build-essential gcc neovim fish less iputils-ping postgresql-client \
ack
ADD requirements/main.txt \
requirements/dev.txt \
requirements/production.txt \
./requirements/

# Copy dependency specification files
COPY pyproject.toml uv.lock README.md ./

RUN --mount=type=cache,target=/root/.cache \
pip install -U pip uv ruff && \
python -m uv pip install \
-r requirements/main.txt \
-r requirements/dev.txt \
-r requirements/production.txt aws
uv sync --group production --no-install-project

FROM compile-stage AS tests-stage

4 changes: 2 additions & 2 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -56,7 +56,7 @@ If you prefer to develop without Docker:
3. Ensure you are running Python 3.13: `python -V` should output `Python 3.13.x`
4. Create a virtualenv: `python3 -m venv pythonie-venv`
5. Activate the virtualenv: `source pythonie-venv/bin/activate`
6. Install dependencies: `pip install -r requirements.txt` (or `uv pip install -r requirements.txt`)
6. Install uv and dependencies: `pip install uv && uv sync`
7. Set up the database: `python pythonie/manage.py migrate --settings=pythonie.settings.dev`
8. Generate sample data: `python pythonie/manage.py generate_sample_data --settings=pythonie.settings.dev`
9. Create a superuser: `python pythonie/manage.py createsuperuser --settings=pythonie.settings.dev`
Expand DownExpand Up@@ -259,7 +259,7 @@ This project uses several tools to streamline development:

### Import Errors or Module Not Found
- Rebuild Docker image: `task docker:build`
- Reinstall dependencies: `pip install -r requirements.txt`
- Reinstall dependencies: `uv sync`

## Contributing

Expand Down
47 changes: 27 additions & 20 deletions Taskfile.yaml
Original file line numberDiff line numberDiff line change
Expand Up@@ -135,40 +135,49 @@ tasks:
cmds:
- docker compose run --rm web python pythonie/manage.py collectstatic

dependencies:compute:
desc: Compute the dependencies
dependencies:lock:
desc: Update uv.lock file from pyproject.toml
cmds:
- toast deps:compute
- uv lock

dependencies:outdated:
desc: List the outdated dependencies
dependencies:upgrade:
desc: Upgrade all dependencies
cmds:
- toast deps:outdated
- uv lock --upgrade

dependencies:upgrade:
desc: Upgrade the dependencies
dependencies:sync:
desc: Install dependencies from lock file (development)
cmds:
- toast deps:upgrade
- uv sync

dependencies:upgrade:django:
desc: Upgrade Django to the latest compatible version
dependencies:sync:production:
desc: Install production dependencies only
cmds:
- toast deps:upgrade:django
- uv sync --no-dev --group production

dependencies:upgrade:wagtail:
desc: Upgrade Wagtail to the latest compatible version
dependencies:export:
desc: Export uv.lock to requirements.txt for Heroku
cmds:
- toast deps:upgrade:wagtail
- uv export --no-dev --group production -o requirements.txt
- uv export --group dev --group production -o requirements-dev.txt
- |
echo "# AUTO-GENERATED from pyproject.toml - DO NOT EDIT" | cat - requirements.txt > temp && mv temp requirements.txt
echo "# AUTO-GENERATED from pyproject.toml - DO NOT EDIT" | cat - requirements-dev.txt > temp && mv temp requirements-dev.txt

dependencies:outdated:
desc: List the outdated dependencies
cmds:
- toast deps:outdated

dependencies:security:
desc: Check dependencies for known security vulnerabilities
cmds:
- toast deps:security
- uv run pip-audit

dependencies:tree:
desc: Show the dependencies tree
cmds:
- toast deps:tree
- uv tree

docker:build:
desc: Build the docker image
Expand DownExpand Up@@ -213,9 +222,7 @@ tasks:
dependencies:upgrade:package:
desc: "Upgrade a specific package (usage: task dependencies:upgrade:package PACKAGE=django)"
cmds:
- python -m uv pip compile --upgrade-package $PACKAGE --output-file requirements/main.txt requirements/main.in
- python -m uv pip compile --upgrade-package $PACKAGE --output-file requirements/dev.txt requirements/dev.in
- python -m uv pip compile --upgrade-package $PACKAGE --output-file requirements/production.txt requirements/production.in
- uv lock --upgrade-package {{.PACKAGE}}

tests:
desc: Run all tests
Expand Down
135 changes: 135 additions & 0 deletions pyproject.toml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "pythonie"
version = "2025.12.23"
description = "Python Ireland website - Django/Wagtail CMS for python.ie and pycon.ie"
readme = "README.md"
requires-python = ">=3.13.0"
license = {text = "MIT"}
authors = [{name = "Python Ireland", email = "info@python.ie"}]
keywords = ["django", "wagtail", "cms", "python-ireland", "pycon"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Framework :: Django :: 5.2",
"Framework :: Wagtail :: 7",
"Programming Language :: Python :: 3.13",
"License :: OSI Approved :: MIT License",
]

# Main production dependencies (from requirements/main.in)
dependencies = [
"Delorean",
"Django>=5.2.0,<5.3", # Reste sur Django 5.2.x
"Willow",
"boto3",
"colander",
"defusedxml",
"dj-database-url",
"dj-static",
"django-compressor",
"django-extensions",
"django-libsass",
"django-modelcluster",
"django-storages",
"django-taggit",
"gunicorn",
"pandas",
"pydantic",
"python-dateutil",
"pytz",
"redis",
"requests>=2.32.5",
"wagtail>=7.2.0,<7.3", # Wagtail 7.2.x compatible avec Django 5.2
"whitenoise",
]

# PEP 735 Dependency Groups
[dependency-groups]
# Development dependencies (from requirements/dev.in)
dev = [
"coverage",
"django-debug-toolbar",
"factory-boy",
"fakeredis",
"isort",
"model_mommy",
"pip-audit",
"pipdeptree",
"ruff",
"uv",
]

# Production-specific dependencies (from requirements/production.in)
production = [
"psycopg[binary]",
]

# Tool configurations
[tool.ruff]
target-version = "py313"
line-length = 88
exclude = [
"migrations",
".venv",
"venv",
"pythonie-venv",
".git",
"__pycache__",
]

[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"F", # pyflakes
"I", # isort
"N", # pep8-naming
"W", # pycodestyle warnings
"UP", # pyupgrade
"DJ", # django-specific rules
]
ignore = [
"E501", # Line too long (handled by formatter)
]

[tool.ruff.lint.isort]
known-first-party = ["pythonie", "core", "meetups", "speakers", "sponsors"]
section-order = ["future", "standard-library", "third-party", "django", "wagtail", "first-party", "local-folder"]

[tool.ruff.lint.isort.sections]
"django" = ["django"]
"wagtail" = ["wagtail"]

[tool.ruff.format]
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false
line-ending = "auto"

[tool.coverage.run]
source = ["pythonie"]
omit = [
"*/migrations/*",
"*/tests/*",
"*/test_*.py",
"*/__pycache__/*",
"*/venv/*",
"*/.venv/*",
]

[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"def __repr__",
"raise AssertionError",
"raise NotImplementedError",
"if __name__ == .__main__.:",
]

[tool.django-stubs]
django_settings_module = "pythonie.settings.dev"

[tool.hatchling.build.targets.wheel]
packages = ["pythonie"]
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Draft
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
10 changes: 5 additions & 5 deletions .github/workflows/test.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,14 +9,14 @@ jobs:
DJANGO_SETTINGS_MODULE: pythonie.settings.tests
steps:
- uses: actions/checkout@v2
- name: Set Up Python 3.12
- name: Set Up Python 3.13
uses: actions/setup-python@v2
Comment on lines +12 to 13

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you consider setup-uv action instead of setup-python? It can install Python versions just fine, and yields a cleaner result in overall config in my experience.

with:
python-version: "3.12"
python-version: "3.13"
- name: Install the dependencies
run: |
python -m pip install --upgrade pip setuptools uv
python -m uv pip install -r requirements/main.txt -r requirements/dev.txt
python -m pip install --upgrade pip uv
uv sync
- name: Run the tests
run: |
python pythonie/manage.py test pythonie --verbosity=2
uv run python pythonie/manage.py test pythonie --verbosity=2
1 change: 1 addition & 0 deletions .tool-versions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
python 3.13.9
task 3.37.2
uv 0.9.18
57 changes: 46 additions & 11 deletions CLAUDE.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,7 +57,8 @@ Always specify settings module: `--settings=pythonie.settings.dev` (or `tests`,
# Setup
python3 -m venv pythonie-venv
source pythonie-venv/bin/activate
pip install -r requirements.txt
pip install uv
uv sync

# Database
python pythonie/manage.py migrate --settings=pythonie.settings.dev
Expand DownExpand Up@@ -128,32 +129,66 @@ task code:check

### Dependency Management

Uses `uv` for fast Python package management. Dependencies are defined in `.in` files and compiled to `.txt` files:
Uses `uv` with `pyproject.toml` for dependency management. Dependencies are defined in `pyproject.toml` and locked in `uv.lock`:

```bash
# Recompile all dependencies
task dependencies:compute
# or: toast deps:compute
**Structure:**
- `pyproject.toml` - Dependency specifications (edit this to add/remove dependencies)
- `uv.lock` - Locked versions (auto-generated, commit to git)
- `requirements.txt` - Auto-generated for Heroku deployment

# Check outdated packages
task dependencies:outdated
**Common Commands:**

```bash
# Update lock file after changing pyproject.toml
task dependencies:lock

# Upgrade all dependencies
task dependencies:upgrade

# Upgrade only Wagtail
task dependencies:upgrade:wagtail

# Upgrade specific package
task dependencies:upgrade:package PACKAGE=django

# Install dependencies (development)
task dependencies:sync

# Install production dependencies only
task dependencies:sync:production

# Generate requirements.txt for Heroku
task dependencies:export

# Check outdated packages
task dependencies:outdated

# Check for security vulnerabilities
task dependencies:security

# Show dependencies tree
task dependencies:tree
```

**Adding a New Dependency:**

1. Edit `pyproject.toml` to add the dependency:
```toml
dependencies = [
"new-package",
# ...
]
```

2. Update lock and generate requirements.txt:
```bash
task dependencies:lock
task dependencies:export
```

3. Commit both files:
```bash
git add pyproject.toml uv.lock requirements.txt
git commit -m "Add new-package dependency"
```

### Database Operations (Heroku)

```bash
Expand Down
3 changes: 2 additions & 1 deletion CONTRIBUTING.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -85,7 +85,8 @@ python3.13 -m venv pythonie-venv
source pythonie-venv/bin/activate

# Install dependencies
pip install -r requirements/dev.txt
pip install uv
uv sync

# Run migrations
python pythonie/manage.py migrate --settings=pythonie.settings.dev
Expand Down
5 changes: 3 additions & 2 deletions DEVELOPMENT.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -168,7 +168,8 @@ python3.13 -m venv pythonie-venv
source pythonie-venv/bin/activate

# 2. Install dependencies
pip install -r requirements/dev.txt
pip install uv
uv sync

# 3. Migrate database
python pythonie/manage.py migrate --settings=pythonie.settings.dev
Expand DownExpand Up@@ -685,7 +686,7 @@ echo "django-debug-toolbar" >> requirements/main.in
uv pip compile requirements/main.in -o requirements/main.txt

# Install
pip install -r requirements/dev.txt
uv sync
```

### Database Migrations
Expand Down
13 changes: 5 additions & 8 deletions Dockerfile
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,16 +5,13 @@ RUN --mount=type=cache,target=/var/cache/apt \
apt install -y --no-install-recommends \
build-essential gcc neovim fish less iputils-ping postgresql-client \
ack
ADD requirements/main.txt \
requirements/dev.txt \
requirements/production.txt \
./requirements/

# Copy dependency specification files
COPY pyproject.toml uv.lock README.md ./

RUN --mount=type=cache,target=/root/.cache \
pip install -U pip uv ruff && \
python -m uv pip install \
-r requirements/main.txt \
-r requirements/dev.txt \
-r requirements/production.txt aws
uv sync --group production --no-install-project

FROM compile-stage AS tests-stage

4 changes: 2 additions & 2 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -56,7 +56,7 @@ If you prefer to develop without Docker:
3. Ensure you are running Python 3.13: `python -V` should output `Python 3.13.x`
4. Create a virtualenv: `python3 -m venv pythonie-venv`
5. Activate the virtualenv: `source pythonie-venv/bin/activate`
6. Install dependencies: `pip install -r requirements.txt` (or `uv pip install -r requirements.txt`)
6. Install uv and dependencies: `pip install uv && uv sync`
7. Set up the database: `python pythonie/manage.py migrate --settings=pythonie.settings.dev`
8. Generate sample data: `python pythonie/manage.py generate_sample_data --settings=pythonie.settings.dev`
9. Create a superuser: `python pythonie/manage.py createsuperuser --settings=pythonie.settings.dev`
Expand DownExpand Up@@ -259,7 +259,7 @@ This project uses several tools to streamline development:

### Import Errors or Module Not Found
- Rebuild Docker image: `task docker:build`
- Reinstall dependencies: `pip install -r requirements.txt`
- Reinstall dependencies: `uv sync`

## Contributing

Expand Down
47 changes: 27 additions & 20 deletions Taskfile.yaml
Original file line numberDiff line numberDiff line change
Expand Up@@ -135,40 +135,49 @@ tasks:
cmds:
- docker compose run --rm web python pythonie/manage.py collectstatic

dependencies:compute:
desc: Compute the dependencies
dependencies:lock:
desc: Update uv.lock file from pyproject.toml
cmds:
- toast deps:compute
- uv lock

dependencies:outdated:
desc: List the outdated dependencies
dependencies:upgrade:
desc: Upgrade all dependencies
cmds:
- toast deps:outdated
- uv lock --upgrade

dependencies:upgrade:
desc: Upgrade the dependencies
dependencies:sync:
desc: Install dependencies from lock file (development)
cmds:
- toast deps:upgrade
- uv sync

dependencies:upgrade:django:
desc: Upgrade Django to the latest compatible version
dependencies:sync:production:
desc: Install production dependencies only
cmds:
- toast deps:upgrade:django
- uv sync --no-dev --group production

dependencies:upgrade:wagtail:
desc: Upgrade Wagtail to the latest compatible version
dependencies:export:
desc: Export uv.lock to requirements.txt for Heroku
cmds:
- toast deps:upgrade:wagtail
- uv export --no-dev --group production -o requirements.txt
- uv export --group dev --group production -o requirements-dev.txt
- |
echo "# AUTO-GENERATED from pyproject.toml - DO NOT EDIT" | cat - requirements.txt > temp && mv temp requirements.txt
echo "# AUTO-GENERATED from pyproject.toml - DO NOT EDIT" | cat - requirements-dev.txt > temp && mv temp requirements-dev.txt

dependencies:outdated:
desc: List the outdated dependencies
cmds:
- toast deps:outdated

dependencies:security:
desc: Check dependencies for known security vulnerabilities
cmds:
- toast deps:security
- uv run pip-audit

dependencies:tree:
desc: Show the dependencies tree
cmds:
- toast deps:tree
- uv tree

docker:build:
desc: Build the docker image
Expand DownExpand Up@@ -213,9 +222,7 @@ tasks:
dependencies:upgrade:package:
desc: "Upgrade a specific package (usage: task dependencies:upgrade:package PACKAGE=django)"
cmds:
- python -m uv pip compile --upgrade-package $PACKAGE --output-file requirements/main.txt requirements/main.in
- python -m uv pip compile --upgrade-package $PACKAGE --output-file requirements/dev.txt requirements/dev.in
- python -m uv pip compile --upgrade-package $PACKAGE --output-file requirements/production.txt requirements/production.in
- uv lock --upgrade-package {{.PACKAGE}}

tests:
desc: Run all tests
Expand Down
135 changes: 135 additions & 0 deletions pyproject.toml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "pythonie"
version = "2025.12.23"
description = "Python Ireland website - Django/Wagtail CMS for python.ie and pycon.ie"
readme = "README.md"
requires-python = ">=3.13.0"
license = {text = "MIT"}
authors = [{name = "Python Ireland", email = "info@python.ie"}]
keywords = ["django", "wagtail", "cms", "python-ireland", "pycon"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Framework :: Django :: 5.2",
"Framework :: Wagtail :: 7",
"Programming Language :: Python :: 3.13",
"License :: OSI Approved :: MIT License",
]

# Main production dependencies (from requirements/main.in)
dependencies = [
"Delorean",
"Django>=5.2.0,<5.3", # Reste sur Django 5.2.x
"Willow",
"boto3",
"colander",
"defusedxml",
"dj-database-url",
"dj-static",
"django-compressor",
"django-extensions",
"django-libsass",
"django-modelcluster",
"django-storages",
"django-taggit",
"gunicorn",
"pandas",
"pydantic",
"python-dateutil",
"pytz",
"redis",
"requests>=2.32.5",
"wagtail>=7.2.0,<7.3", # Wagtail 7.2.x compatible avec Django 5.2
"whitenoise",
]

# PEP 735 Dependency Groups
[dependency-groups]
# Development dependencies (from requirements/dev.in)
dev = [
"coverage",
"django-debug-toolbar",
"factory-boy",
"fakeredis",
"isort",
"model_mommy",
"pip-audit",
"pipdeptree",
"ruff",
"uv",
]

# Production-specific dependencies (from requirements/production.in)
production = [
"psycopg[binary]",
]

# Tool configurations
[tool.ruff]
target-version = "py313"
line-length = 88
exclude = [
"migrations",
".venv",
"venv",
"pythonie-venv",
".git",
"__pycache__",
]

[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"F", # pyflakes
"I", # isort
"N", # pep8-naming
"W", # pycodestyle warnings
"UP", # pyupgrade
"DJ", # django-specific rules
]
ignore = [
"E501", # Line too long (handled by formatter)
]

[tool.ruff.lint.isort]
known-first-party = ["pythonie", "core", "meetups", "speakers", "sponsors"]
section-order = ["future", "standard-library", "third-party", "django", "wagtail", "first-party", "local-folder"]

[tool.ruff.lint.isort.sections]
"django" = ["django"]
"wagtail" = ["wagtail"]

[tool.ruff.format]
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false
line-ending = "auto"

[tool.coverage.run]
source = ["pythonie"]
omit = [
"*/migrations/*",
"*/tests/*",
"*/test_*.py",
"*/__pycache__/*",
"*/venv/*",
"*/.venv/*",
]

[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"def __repr__",
"raise AssertionError",
"raise NotImplementedError",
"if __name__ == .__main__.:",
]

[tool.django-stubs]
django_settings_module = "pythonie.settings.dev"

[tool.hatchling.build.targets.wheel]
packages = ["pythonie"]
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Draft
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
10 changes: 5 additions & 5 deletions .github/workflows/test.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,14 +9,14 @@ jobs:
DJANGO_SETTINGS_MODULE: pythonie.settings.tests
steps:
- uses: actions/checkout@v2
- name: Set Up Python 3.12
- name: Set Up Python 3.13
uses: actions/setup-python@v2
Comment on lines +12 to 13

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you consider setup-uv action instead of setup-python? It can install Python versions just fine, and yields a cleaner result in overall config in my experience.

with:
python-version: "3.12"
python-version: "3.13"
- name: Install the dependencies
run: |
python -m pip install --upgrade pip setuptools uv
python -m uv pip install -r requirements/main.txt -r requirements/dev.txt
python -m pip install --upgrade pip uv
uv sync
- name: Run the tests
run: |
python pythonie/manage.py test pythonie --verbosity=2
uv run python pythonie/manage.py test pythonie --verbosity=2
1 change: 1 addition & 0 deletions .tool-versions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
python 3.13.9
task 3.37.2
uv 0.9.18
57 changes: 46 additions & 11 deletions CLAUDE.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,7 +57,8 @@ Always specify settings module: `--settings=pythonie.settings.dev` (or `tests`,
# Setup
python3 -m venv pythonie-venv
source pythonie-venv/bin/activate
pip install -r requirements.txt
pip install uv
uv sync

# Database
python pythonie/manage.py migrate --settings=pythonie.settings.dev
Expand DownExpand Up@@ -128,32 +129,66 @@ task code:check

### Dependency Management

Uses `uv` for fast Python package management. Dependencies are defined in `.in` files and compiled to `.txt` files:
Uses `uv` with `pyproject.toml` for dependency management. Dependencies are defined in `pyproject.toml` and locked in `uv.lock`:

```bash
# Recompile all dependencies
task dependencies:compute
# or: toast deps:compute
**Structure:**
- `pyproject.toml` - Dependency specifications (edit this to add/remove dependencies)
- `uv.lock` - Locked versions (auto-generated, commit to git)
- `requirements.txt` - Auto-generated for Heroku deployment

# Check outdated packages
task dependencies:outdated
**Common Commands:**

```bash
# Update lock file after changing pyproject.toml
task dependencies:lock

# Upgrade all dependencies
task dependencies:upgrade

# Upgrade only Wagtail
task dependencies:upgrade:wagtail

# Upgrade specific package
task dependencies:upgrade:package PACKAGE=django

# Install dependencies (development)
task dependencies:sync

# Install production dependencies only
task dependencies:sync:production

# Generate requirements.txt for Heroku
task dependencies:export

# Check outdated packages
task dependencies:outdated

# Check for security vulnerabilities
task dependencies:security

# Show dependencies tree
task dependencies:tree
```

**Adding a New Dependency:**

1. Edit `pyproject.toml` to add the dependency:
```toml
dependencies = [
"new-package",
# ...
]
```

2. Update lock and generate requirements.txt:
```bash
task dependencies:lock
task dependencies:export
```

3. Commit both files:
```bash
git add pyproject.toml uv.lock requirements.txt
git commit -m "Add new-package dependency"
```

### Database Operations (Heroku)

```bash
Expand Down
3 changes: 2 additions & 1 deletion CONTRIBUTING.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -85,7 +85,8 @@ python3.13 -m venv pythonie-venv
source pythonie-venv/bin/activate

# Install dependencies
pip install -r requirements/dev.txt
pip install uv
uv sync

# Run migrations
python pythonie/manage.py migrate --settings=pythonie.settings.dev
Expand Down
5 changes: 3 additions & 2 deletions DEVELOPMENT.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -168,7 +168,8 @@ python3.13 -m venv pythonie-venv
source pythonie-venv/bin/activate

# 2. Install dependencies
pip install -r requirements/dev.txt
pip install uv
uv sync

# 3. Migrate database
python pythonie/manage.py migrate --settings=pythonie.settings.dev
Expand DownExpand Up@@ -685,7 +686,7 @@ echo "django-debug-toolbar" >> requirements/main.in
uv pip compile requirements/main.in -o requirements/main.txt

# Install
pip install -r requirements/dev.txt
uv sync
```

### Database Migrations
Expand Down
13 changes: 5 additions & 8 deletions Dockerfile
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,16 +5,13 @@ RUN --mount=type=cache,target=/var/cache/apt \
apt install -y --no-install-recommends \
build-essential gcc neovim fish less iputils-ping postgresql-client \
ack
ADD requirements/main.txt \
requirements/dev.txt \
requirements/production.txt \
./requirements/

# Copy dependency specification files
COPY pyproject.toml uv.lock README.md ./

RUN --mount=type=cache,target=/root/.cache \
pip install -U pip uv ruff && \
python -m uv pip install \
-r requirements/main.txt \
-r requirements/dev.txt \
-r requirements/production.txt aws
uv sync --group production --no-install-project

FROM compile-stage AS tests-stage

4 changes: 2 additions & 2 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -56,7 +56,7 @@ If you prefer to develop without Docker:
3. Ensure you are running Python 3.13: `python -V` should output `Python 3.13.x`
4. Create a virtualenv: `python3 -m venv pythonie-venv`
5. Activate the virtualenv: `source pythonie-venv/bin/activate`
6. Install dependencies: `pip install -r requirements.txt` (or `uv pip install -r requirements.txt`)
6. Install uv and dependencies: `pip install uv && uv sync`
7. Set up the database: `python pythonie/manage.py migrate --settings=pythonie.settings.dev`
8. Generate sample data: `python pythonie/manage.py generate_sample_data --settings=pythonie.settings.dev`
9. Create a superuser: `python pythonie/manage.py createsuperuser --settings=pythonie.settings.dev`
Expand DownExpand Up@@ -259,7 +259,7 @@ This project uses several tools to streamline development:

### Import Errors or Module Not Found
- Rebuild Docker image: `task docker:build`
- Reinstall dependencies: `pip install -r requirements.txt`
- Reinstall dependencies: `uv sync`

## Contributing

Expand Down
47 changes: 27 additions & 20 deletions Taskfile.yaml
Original file line numberDiff line numberDiff line change
Expand Up@@ -135,40 +135,49 @@ tasks:
cmds:
- docker compose run --rm web python pythonie/manage.py collectstatic

dependencies:compute:
desc: Compute the dependencies
dependencies:lock:
desc: Update uv.lock file from pyproject.toml
cmds:
- toast deps:compute
- uv lock

dependencies:outdated:
desc: List the outdated dependencies
dependencies:upgrade:
desc: Upgrade all dependencies
cmds:
- toast deps:outdated
- uv lock --upgrade

dependencies:upgrade:
desc: Upgrade the dependencies
dependencies:sync:
desc: Install dependencies from lock file (development)
cmds:
- toast deps:upgrade
- uv sync

dependencies:upgrade:django:
desc: Upgrade Django to the latest compatible version
dependencies:sync:production:
desc: Install production dependencies only
cmds:
- toast deps:upgrade:django
- uv sync --no-dev --group production

dependencies:upgrade:wagtail:
desc: Upgrade Wagtail to the latest compatible version
dependencies:export:
desc: Export uv.lock to requirements.txt for Heroku
cmds:
- toast deps:upgrade:wagtail
- uv export --no-dev --group production -o requirements.txt
- uv export --group dev --group production -o requirements-dev.txt
- |
echo "# AUTO-GENERATED from pyproject.toml - DO NOT EDIT" | cat - requirements.txt > temp && mv temp requirements.txt
echo "# AUTO-GENERATED from pyproject.toml - DO NOT EDIT" | cat - requirements-dev.txt > temp && mv temp requirements-dev.txt

dependencies:outdated:
desc: List the outdated dependencies
cmds:
- toast deps:outdated

dependencies:security:
desc: Check dependencies for known security vulnerabilities
cmds:
- toast deps:security
- uv run pip-audit

dependencies:tree:
desc: Show the dependencies tree
cmds:
- toast deps:tree
- uv tree

docker:build:
desc: Build the docker image
Expand DownExpand Up@@ -213,9 +222,7 @@ tasks:
dependencies:upgrade:package:
desc: "Upgrade a specific package (usage: task dependencies:upgrade:package PACKAGE=django)"
cmds:
- python -m uv pip compile --upgrade-package $PACKAGE --output-file requirements/main.txt requirements/main.in
- python -m uv pip compile --upgrade-package $PACKAGE --output-file requirements/dev.txt requirements/dev.in
- python -m uv pip compile --upgrade-package $PACKAGE --output-file requirements/production.txt requirements/production.in
- uv lock --upgrade-package {{.PACKAGE}}

tests:
desc: Run all tests
Expand Down
135 changes: 135 additions & 0 deletions pyproject.toml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "pythonie"
version = "2025.12.23"
description = "Python Ireland website - Django/Wagtail CMS for python.ie and pycon.ie"
readme = "README.md"
requires-python = ">=3.13.0"
license = {text = "MIT"}
authors = [{name = "Python Ireland", email = "info@python.ie"}]
keywords = ["django", "wagtail", "cms", "python-ireland", "pycon"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Framework :: Django :: 5.2",
"Framework :: Wagtail :: 7",
"Programming Language :: Python :: 3.13",
"License :: OSI Approved :: MIT License",
]

# Main production dependencies (from requirements/main.in)
dependencies = [
"Delorean",
"Django>=5.2.0,<5.3", # Reste sur Django 5.2.x
"Willow",
"boto3",
"colander",
"defusedxml",
"dj-database-url",
"dj-static",
"django-compressor",
"django-extensions",
"django-libsass",
"django-modelcluster",
"django-storages",
"django-taggit",
"gunicorn",
"pandas",
"pydantic",
"python-dateutil",
"pytz",
"redis",
"requests>=2.32.5",
"wagtail>=7.2.0,<7.3", # Wagtail 7.2.x compatible avec Django 5.2
"whitenoise",
]

# PEP 735 Dependency Groups
[dependency-groups]
# Development dependencies (from requirements/dev.in)
dev = [
"coverage",
"django-debug-toolbar",
"factory-boy",
"fakeredis",
"isort",
"model_mommy",
"pip-audit",
"pipdeptree",
"ruff",
"uv",
]

# Production-specific dependencies (from requirements/production.in)
production = [
"psycopg[binary]",
]

# Tool configurations
[tool.ruff]
target-version = "py313"
line-length = 88
exclude = [
"migrations",
".venv",
"venv",
"pythonie-venv",
".git",
"__pycache__",
]

[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"F", # pyflakes
"I", # isort
"N", # pep8-naming
"W", # pycodestyle warnings
"UP", # pyupgrade
"DJ", # django-specific rules
]
ignore = [
"E501", # Line too long (handled by formatter)
]

[tool.ruff.lint.isort]
known-first-party = ["pythonie", "core", "meetups", "speakers", "sponsors"]
section-order = ["future", "standard-library", "third-party", "django", "wagtail", "first-party", "local-folder"]

[tool.ruff.lint.isort.sections]
"django" = ["django"]
"wagtail" = ["wagtail"]

[tool.ruff.format]
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false
line-ending = "auto"

[tool.coverage.run]
source = ["pythonie"]
omit = [
"*/migrations/*",
"*/tests/*",
"*/test_*.py",
"*/__pycache__/*",
"*/venv/*",
"*/.venv/*",
]

[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"def __repr__",
"raise AssertionError",
"raise NotImplementedError",
"if __name__ == .__main__.:",
]

[tool.django-stubs]
django_settings_module = "pythonie.settings.dev"

[tool.hatchling.build.targets.wheel]
packages = ["pythonie"]
Loading