Skip to content

Commit 61f1edf

Browse files
authored
Full Windows support (#599)
- Replaces hardcoded Unix paths (`/tmp`) with repository-local temporary directories for better cross-platform compatibility - Adds GPG availability detection and conditional test skipping to handle environments where GPG is not installed - Implements Windows-specific fixes for SQLite backup temporary file handling to resolve file locking issues
1 parent 619819c commit 61f1edf

File tree

19 files changed

+395
-216
lines changed

19 files changed

+395
-216
lines changed

.editorconfig

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# http://editorconfig.org
2+
3+
root = true
4+
5+
[*]
6+
indent_style = space
7+
indent_size = 2
8+
insert_final_newline = true
9+
trim_trailing_whitespace = true
10+
charset = utf-8
11+
end_of_line = lf
12+
13+
[*.py]
14+
indent_size = 4
15+
max_line_length = 120
16+
17+
[*.md]
18+
indent_size = 2
19+
20+
[*.html]
21+
max_line_length = off
22+
23+
[*.js]
24+
max_line_length = off
25+
26+
[*.css]
27+
indent_size = 4
28+
max_line_length = off
29+
30+
# Tests can violate line width restrictions in the interest of clarity.
31+
[**/test_*.py]
32+
max_line_length = off
33+
34+
[*.yml]
35+
indent_size = 4

.github/copilot-instructions.md

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,30 @@ Always reference these instructions first and fallback to search or bash command
99
## Working Effectively
1010

1111
Bootstrap, build, and test the repository:
12+
1213
- `python -m pip install --upgrade pip hatch uv` - installs modern Python tooling (takes ~30 seconds)
1314
- `hatch test` - runs comprehensive unit test suite across all Python/Django versions. Takes ~30 seconds. NEVER CANCEL. **All tests must always pass - failures are never expected or allowed.**
1415
- `hatch run functional:test` - runs end-to-end functional tests for backup/restore workflows. Takes ~10 seconds. NEVER CANCEL.
1516
- `hatch run lint:check` - runs linting on the main package. Takes ~5 seconds. NEVER CANCEL.
1617
- `hatch run lint:format-check` - runs code formatting checks. Takes ~2 seconds. NEVER CANCEL.
1718

1819
Build documentation:
20+
1921
- `hatch run docs:build` - builds HTML documentation with MkDocs Material. Takes ~2 seconds. NEVER CANCEL.
2022
- `hatch run docs:serve` - serves documentation locally on http://localhost:8000 for development
2123

2224
## Testing and Validation
2325

2426
Run tests in multiple configurations:
27+
2528
- `hatch test` - unit test runner for all environments (30 seconds) **All tests must always pass - failures are never expected or allowed.**
2629
- `hatch test --python 3.12` - test on specific Python version (10 seconds)
2730
- `hatch run functional:test` - complete backup/restore test cycle in real filesystem environment (10 seconds)
2831
- `hatch run lint:check` - linting on main package (5 seconds)
2932
- `hatch run lint:format` - auto-format code using Ruff (2 seconds)
3033

3134
Expected test results:
35+
3236
- Unit tests: >200 tests, completes in ~30 seconds across all environments **All tests must always pass - failures are never expected or allowed.**
3337
- Functional tests: database and media backup/restore cycles, completes in ~10 seconds
3438
- All tests use a SQLite filesystem database by default
@@ -38,11 +42,13 @@ Expected test results:
3842
Always test backup and restore functionality after making changes using functional test environment:
3943

4044
1. **Database Backup/Restore Test:**
45+
4146
```bash
4247
hatch run functional:test # Comprehensive automated test
4348
```
4449

4550
2. **Manual Database Test (if needed):**
51+
4652
```bash
4753
hatch shell functional
4854
python -m django migrate --noinput
@@ -54,12 +60,12 @@ Always test backup and restore functionality after making changes using function
5460
3. **Manual Media Test (if needed):**
5561
```bash
5662
hatch shell functional
57-
mkdir -p /tmp/media
58-
echo "test file" > /tmp/media/test.txt
63+
mkdir -p tmp/media
64+
echo "test file" > tmp/media/test.txt
5965
python -m django mediabackup --noinput
60-
rm /tmp/media/test.txt
66+
rm tmp/media/test.txt
6167
python -m django mediarestore --noinput
62-
ls /tmp/media/ # should show restored test.txt
68+
ls tmp/media/ # should show restored test.txt
6369
```
6470

6571
## Troubleshooting Known Issues
@@ -73,10 +79,11 @@ Always test backup and restore functionality after making changes using function
7379
## Development Workflow
7480

7581
Modern development process using Hatch:
82+
7683
1. **Bootstrap environment**: `pip install --upgrade pip hatch uv`
7784
2. **Make your changes** to the codebase
7885
3. **Run unit tests**: `hatch test` (30 seconds) **All tests must always pass - failures are never expected or allowed.**
79-
4. **Run functional tests**: `hatch run functional:test` (10 seconds)
86+
4. **Run functional tests**: `hatch run functional:test` (10 seconds)
8087
5. **Run linting**: `hatch run lint:check` (5 seconds)
8188
6. **Auto-format code**: `hatch run lint:format` (2 seconds)
8289
7. **Test documentation**: `hatch run docs:build` (2 seconds)
@@ -89,9 +96,10 @@ Always run `hatch run lint:check` before committing. The CI (.github/workflows/b
8996
## Repository Structure and Navigation
9097

9198
Key directories and files:
99+
92100
- `dbbackup/` - main package code
93101
- `management/commands/` - Django management commands (dbbackup, dbrestore, etc.)
94-
- `db/` - database connector implementations (MySQL, PostgreSQL, SQLite, etc.)
102+
- `db/` - database connector implementations (MySQL, PostgreSQL, SQLite, etc.)
95103
- `storage.py` - storage backend interface
96104
- `tests/` - comprehensive test suite
97105
- `docs/` - MkDocs Material documentation source
@@ -100,6 +108,7 @@ Key directories and files:
100108
- `conftest.py` - pytest configuration for Django test setup
101109

102110
Key configuration files:
111+
103112
- `pyproject.toml` - all tool configuration (hatch, ruff, pylint, pytest, coverage)
104113
- `.pre-commit-config.yaml` - git pre-commit hooks setup
105114
- `dbbackup/tests/settings.py` - Django test settings with EMAIL_BACKEND for testing
@@ -109,9 +118,10 @@ Key configuration files:
109118
The following are key commands for daily development:
110119

111120
### Development Commands
121+
112122
```bash
113123
hatch test # Run all tests across environments
114-
hatch test --python 3.12 # Test specific Python version
124+
hatch test --python 3.12 # Test specific Python version
115125
hatch run functional:test # End-to-end backup/restore tests
116126
hatch run lint:check # Run linting (ruff + pylint)
117127
hatch run lint:format # Auto-format code
@@ -122,6 +132,7 @@ hatch build # Build distribution packages
122132
```
123133

124134
### Environment Management
135+
125136
```bash
126137
hatch env show # Show all environments
127138
hatch shell # Enter default shell
@@ -134,52 +145,60 @@ hatch run --env lint ruff --version # Run command in specific environment
134145
Modern isolated environments configured in pyproject.toml:
135146

136147
### Testing Environments
148+
137149
- **hatch-test**: Unit testing across Python 3.9-3.13 and Django 4.2-5.2 combinations
138150
- **functional**: End-to-end testing with real filesystem storage
139151

140-
### Development Environments
152+
### Development Environments
153+
141154
- **lint**: Code quality (ruff, pylint)
142155
- **docs**: Documentation building (mkdocs-material)
143156
- **precommit**: Git hooks management
144157

145158
### Test Configuration
146-
- Default database: SQLite file-based (`/tmp/test_db.sqlite3`)
159+
160+
- Default database: SQLite file-based (`tmp/test_db.sqlite3` within the repository)
147161
- Email testing: Django locmem backend (`django.core.mail.backends.locmem.EmailBackend`)
148162
- Settings: `dbbackup.tests.settings`
149163
- Test data models: `dbbackup.tests.testapp.models`
150164

151165
### Build Timing Expectations
166+
152167
- **NEVER CANCEL**: All commands complete within 60 seconds
153168
- Dependency installation: 5-30 seconds (hatch manages automatically)
154169
- Unit tests: 10-30 seconds (varies by environment matrix)
155-
- Functional tests: 5-10 seconds
170+
- Functional tests: 5-10 seconds
156171
- Linting: 2-5 seconds
157172
- Documentation build: 1-2 seconds
158173

159174
### Environment Variables for Testing
175+
160176
- `DJANGO_SETTINGS_MODULE` - Django settings (default: dbbackup.tests.settings)
161177
- `DB_ENGINE` - database engine (default: django.db.backends.sqlite3)
162-
- `DB_NAME` - database name (default: :memory: for unit tests, /tmp/test_db.sqlite3 for functional)
178+
- `DB_NAME` - database name (default: :memory: for unit tests, tmp/test_db.sqlite3 for functional)
163179
- `STORAGE` - storage backend (default: dbbackup.tests.utils.FakeStorage for unit, FileSystemStorage for functional)
164-
- `MEDIA_ROOT` - media files location (default: /tmp/media/)
180+
- `MEDIA_ROOT` - media files location (default: tmp/media/)
165181

166182
## Package Dependencies
167183

168184
Modern dependency management via pyproject.toml:
169185

170186
Core runtime dependencies:
187+
171188
- django>=4.2
172189
- pytz
173190

174191
Development dependencies (managed by hatch):
192+
175193
- **Testing**: coverage, django-storages, psycopg2-binary, python-gnupg, testfixtures
176-
- **Linting**: ruff, pylint
194+
- **Linting**: ruff, pylint
177195
- **Documentation**: mkdocs, mkdocs-material
178196
- **Pre-commit**: pre-commit
179197

180198
## CI/CD Pipeline
181199

182200
Modern GitHub Actions workflow (.github/workflows/build.yml):
201+
183202
- **Lint Python**: Code quality checks (temporarily set to pass)
184203
- **Test Python**: Matrix testing across Python 3.9-3.13 with coverage
185204
- **Functional Tests**: End-to-end backup/restore verification
@@ -192,8 +211,9 @@ Modern GitHub Actions workflow (.github/workflows/build.yml):
192211

193212
- **This is a Django package**, not a standalone application - it provides management commands for Django projects
194213
- **Backup/restore functionality** works with SQLite, MySQL, PostgreSQL databases and various storage backends
195-
- **All builds and tests run quickly** - if something takes more than 60 seconds, investigate network connectivity
214+
- **All builds and tests run quickly** - if something takes more than 60 seconds, investigate network connectivity
196215
- **Hatch environments provide full isolation** - no need to manage virtual environments manually
197216
- **The functional test environment is the gold standard** - it performs real backup and restore operations with filesystem storage
198217
- **Documentation updates are required** when making changes to Python source code
199218
- **Always update this file** when making changes to the development workflow, build process, or repository structure
219+
- **Tests use a repository-local tmp/ directory** instead of system /tmp for portability (especially on Windows) and cleaner CI artifacts.

.github/workflows/ci.yml

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -57,61 +57,56 @@ jobs:
5757
run: hatch run scripts/validate_changelog.py
5858

5959
test-python:
60-
name: Python ${{ matrix.python-version }}
61-
runs-on: ubuntu-latest
60+
name: Python ${{ matrix.python-version }} (${{ matrix.os }})
61+
runs-on: ${{ matrix.os }}
6262
needs:
6363
- lint-python
64-
6564
strategy:
65+
fail-fast: false
6666
matrix:
67+
os: [ubuntu-latest, windows-latest]
6768
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
68-
6969
steps:
7070
- uses: actions/checkout@v4
71-
7271
- uses: actions/setup-python@v5
7372
with:
7473
python-version: ${{ matrix.python-version }}
7574
allow-prereleases: true
7675
cache: pip
77-
7876
- name: Install dependencies
7977
run: python -m pip install --upgrade pip hatch uv
80-
8178
- name: Show environment
8279
run: hatch test --show --python ${{ matrix.python-version }}
83-
8480
- name: Run tests
8581
run: |
8682
hatch test --cover --python ${{ matrix.python-version }}
87-
mv .coverage ".coverage.py${{ matrix.python-version }}"
88-
83+
mv .coverage ".coverage.${{ matrix.os }}.py${{ matrix.python-version }}"
8984
- name: Upload coverage data
9085
uses: actions/upload-artifact@v4
9186
with:
92-
name: "coverage-data-py${{ matrix.python-version }}"
93-
path: ".coverage.py${{ matrix.python-version }}"
87+
name: "coverage-data-${{ matrix.os }}-py${{ matrix.python-version }}"
88+
path: ".coverage.${{ matrix.os }}.py${{ matrix.python-version }}"
9489
if-no-files-found: error
9590
include-hidden-files: true
9691
retention-days: 7
9792

9893
test-functional:
99-
name: Functional Tests
100-
runs-on: ubuntu-latest
94+
name: Functional Tests (${{ matrix.os }})
95+
runs-on: ${{ matrix.os }}
10196
needs:
10297
- lint-python
103-
98+
strategy:
99+
fail-fast: false
100+
matrix:
101+
os: [ubuntu-latest, windows-latest]
104102
steps:
105103
- uses: actions/checkout@v4
106-
107104
- uses: actions/setup-python@v5
108105
with:
109106
python-version: "3.12"
110107
cache: pip
111-
112108
- name: Install dependencies
113109
run: python -m pip install --upgrade pip hatch uv
114-
115110
- name: Run functional tests
116111
run: hatch run functional:test
117112

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ target/
7171
*.sw[po]
7272
test-sqlite
7373
venv
74+
tmp/
7475

7576
# Visual Studio Code #
7677
.vscode/settings.json

0 commit comments

Comments
 (0)