odoo-dev 0.3.1__tar.gz → 0.3.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/.claude/settings.local.json +2 -1
- odoo_dev-0.3.3/PKG-INFO +183 -0
- odoo_dev-0.3.3/README.md +169 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/pyproject.toml +1 -1
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/src/odoo_dev/__init__.py +1 -1
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/src/odoo_dev/commands/run.py +42 -16
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/src/odoo_dev/commands/setup.py +17 -82
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/odoo-empty/.gitignore +1 -0
- odoo_dev-0.3.3/tests/test_drop_database.py +165 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/test_setup.py +50 -0
- odoo_dev-0.3.1/PKG-INFO +0 -19
- odoo_dev-0.3.1/README.md +0 -5
- odoo_dev-0.3.1/tests/fixtures/odoo-empty/.git +0 -1
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/.claude/settings.json +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/.gitignore +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/.gitmodules +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/.python-version +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/src/odoo_dev/cli.py +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/src/odoo_dev/commands/__init__.py +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/src/odoo_dev/commands/db.py +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/src/odoo_dev/commands/docker.py +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/src/odoo_dev/config.py +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/src/odoo_dev/templates/__init__.py +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/src/odoo_dev/templates/docker/Dockerfile +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/src/odoo_dev/templates/docker/__init__.py +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/src/odoo_dev/templates/docker/docker-entrypoint.sh +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/src/odoo_dev/templates/vscode/__init__.py +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/src/odoo_dev/templates/vscode/launch.json +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/src/odoo_dev/templates/vscode/settings.json +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/src/odoo_dev/templates/vscode/tasks.json +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/src/odoo_dev/utils/__init__.py +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/src/odoo_dev/utils/console.py +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/__init__.py +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/__init__.py +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/odoo-empty/.gitlab-ci.yml +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/odoo-empty/.gitmodules +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/odoo-empty/.repos/.gitkeep +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/odoo-empty/Notes/Warning Upgrade all +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/odoo-empty/README.md +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/odoo-empty/addons/.gitkeep +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/odoo-empty/note.txt +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/odoo-empty/requirements.txt +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/odoo-empty/tools/abstorelsymlink.sh +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/odoo-empty/tools/adaptation.md +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/odoo-empty/tools/after_migration.sh +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/odoo-empty/tools/checkout2 +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/odoo-empty/tools/cleanup.sql +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/odoo-empty/tools/deploy +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/odoo-empty/tools/fix_mail_templates.sql +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/odoo-empty/tools/gitpull +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/odoo-empty/tools/main.py +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/odoo-empty/tools/modules_cleanup.sql +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/odoo-empty/tools/post-upgrade steps.md +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/odoo-empty/tools/pre_commit_hook.py +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/odoo-empty/tools/requirements.txt +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/odoo-empty/tools/test +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/fixtures/odoo-empty/tools/update_addon_versions.py +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/test_cli.py +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/test_config.py +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/test_db.py +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/test_integration.py +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/tests/test_run.py +0 -0
- {odoo_dev-0.3.1 → odoo_dev-0.3.3}/uv.lock +0 -0
odoo_dev-0.3.3/PKG-INFO
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: odoo-dev
|
|
3
|
+
Version: 0.3.3
|
|
4
|
+
Summary: Odoo Development Environment Helper
|
|
5
|
+
Project-URL: Homepage, https://git.bemade.org/bemade/odoo-dev
|
|
6
|
+
Project-URL: Repository, https://git.bemade.org/bemade/odoo-dev
|
|
7
|
+
Project-URL: Issues, https://git.bemade.org/bemade/odoo-dev/-/issues
|
|
8
|
+
License-Expression: LGPL-3.0
|
|
9
|
+
Requires-Python: >=3.12
|
|
10
|
+
Requires-Dist: pyyaml>=6.0
|
|
11
|
+
Requires-Dist: rich>=13.0.0
|
|
12
|
+
Requires-Dist: typer>=0.9.0
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
15
|
+
# odoo-dev
|
|
16
|
+
|
|
17
|
+
A CLI tool for managing Odoo development environments. Handles local Python setup, Docker containers, database operations, and more.
|
|
18
|
+
|
|
19
|
+
It is the successor to the older `odoo-deploy` shell scripts — if you have notes for `odoo-deploy`, the rough mapping is: `odoo-dev docker start/stop/build` replaces the old `odoo-dev.sh start/stop/build`, and `odoo-dev run`/`test`/`shell` give you a local (venv-based) workflow that `odoo-deploy` didn't.
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Install with uv (recommended) — installs the published package from PyPI
|
|
25
|
+
uv tool install odoo-dev
|
|
26
|
+
|
|
27
|
+
# Or with pip
|
|
28
|
+
pip install odoo-dev
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Then make sure the install location is on your `PATH` (uv prints the path; usually `~/.local/bin`):
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
uv tool update-shell # or: export PATH="$HOME/.local/bin:$PATH"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Quick Start
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# In your Odoo project directory
|
|
41
|
+
cd my-odoo-project
|
|
42
|
+
|
|
43
|
+
# Full setup: clone Odoo repos, create venv, install deps, configure VSCode
|
|
44
|
+
odoo-dev setup
|
|
45
|
+
|
|
46
|
+
# Or for community edition only
|
|
47
|
+
odoo-dev setup --community
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`setup` reads `ODOO_VERSION` / `PYTHON_VERSION` from a `.env` in the project root (or
|
|
51
|
+
prompts for them and offers to save). It then clones the Odoo repos, builds a `.venv`,
|
|
52
|
+
installs system dependencies, and generates `conf/odoo.conf`. It will offer to set up
|
|
53
|
+
Docker at the end — answer "no" if you only want the local venv workflow.
|
|
54
|
+
|
|
55
|
+
## Database setup (read this before your first `run`/`test`)
|
|
56
|
+
|
|
57
|
+
The generated `conf/odoo.conf` connects as PostgreSQL user **`odoo`** over the local
|
|
58
|
+
socket. You need a running PostgreSQL server and a matching role. `setup` installs
|
|
59
|
+
PostgreSQL but does **not** start it or create the role, so on a fresh machine do this
|
|
60
|
+
once:
|
|
61
|
+
|
|
62
|
+
**macOS (Homebrew):**
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
brew services start postgresql@18 # start the server (use your installed version)
|
|
66
|
+
createuser -s odoo # create the role odoo.conf expects
|
|
67
|
+
# Homebrew's versioned postgres is keg-only; add its bin to PATH if psql/createuser aren't found:
|
|
68
|
+
# export PATH="$(brew --prefix postgresql@18)/bin:$PATH"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Debian/Ubuntu:**
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
sudo systemctl start postgresql
|
|
75
|
+
sudo -u postgres createuser -s odoo
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
You can change the DB user/password in `conf/odoo.conf` if you prefer a different role.
|
|
79
|
+
|
|
80
|
+
## Commands
|
|
81
|
+
|
|
82
|
+
### Local Development (default)
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
odoo-dev run # Start Odoo locally (default port 8069)
|
|
86
|
+
odoo-dev run -d mydb -p 8070 # Pick a database and HTTP port
|
|
87
|
+
odoo-dev run -d mydb -i base # Initialize module(s) on start
|
|
88
|
+
odoo-dev run -d mydb --dev reload # With hot reload
|
|
89
|
+
odoo-dev run --debug # With debugpy (VSCode attach on 5678)
|
|
90
|
+
odoo-dev shell mydb # Open an Odoo shell
|
|
91
|
+
odoo-dev update base -d mydb # Update modules
|
|
92
|
+
odoo-dev test my_module # Run a module's tests (coverage on by default)
|
|
93
|
+
odoo-dev test my_module --test-tags my_module --no-coverage
|
|
94
|
+
odoo-dev test # Auto-discover & test all addons in addons/
|
|
95
|
+
odoo-dev scaffold my_module # Create a new module
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
> Note: the HTTP port flag is `-p` / `--port` (not `--http-port`).
|
|
99
|
+
|
|
100
|
+
### Database Operations
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
odoo-dev db list # List databases
|
|
104
|
+
odoo-dev db restore backup.zip # Restore from backup (neutralized by default)
|
|
105
|
+
odoo-dev db restore backup.zip mydb --no-neutralize
|
|
106
|
+
odoo-dev db drop mydb # Drop database
|
|
107
|
+
odoo-dev db neutralize mydb # Disable emails/crons
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Docker (optional)
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
odoo-dev docker start # Start containers
|
|
114
|
+
odoo-dev docker stop # Stop containers
|
|
115
|
+
odoo-dev docker restart # Restart containers
|
|
116
|
+
odoo-dev docker logs # View logs
|
|
117
|
+
odoo-dev docker build # Rebuild image
|
|
118
|
+
odoo-dev docker shell mydb # Shell in container
|
|
119
|
+
odoo-dev docker psql # PostgreSQL shell
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Setup Commands
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
odoo-dev setup # Full setup
|
|
126
|
+
odoo-dev setup --community # Community edition only
|
|
127
|
+
odoo-dev setup-venv # Just create the venv (no repo clone)
|
|
128
|
+
odoo-dev vscode # Configure VSCode debugging
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Project Structure
|
|
132
|
+
|
|
133
|
+
odoo-dev expects this project structure:
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
my-odoo-project/
|
|
137
|
+
├── .env # Optional: ODOO_VERSION, PYTHON_VERSION
|
|
138
|
+
├── addons/ # Your custom addons
|
|
139
|
+
├── requirements.txt # Project-specific Python deps
|
|
140
|
+
├── odoo/ # Cloned by setup
|
|
141
|
+
├── enterprise/ # Cloned by setup (unless --community)
|
|
142
|
+
├── design-themes/ # Cloned by setup
|
|
143
|
+
├── .venv/ # Created by setup
|
|
144
|
+
└── conf/
|
|
145
|
+
└── odoo.conf # Created by setup
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Configuration
|
|
149
|
+
|
|
150
|
+
Create a `.env` file in your project root:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
ODOO_VERSION=19.0
|
|
154
|
+
PYTHON_VERSION=3.12
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Requirements
|
|
158
|
+
|
|
159
|
+
- Python 3.12+
|
|
160
|
+
- uv (recommended) or pip
|
|
161
|
+
- Git
|
|
162
|
+
- PostgreSQL (for local development — server + an `odoo` role; see "Database setup")
|
|
163
|
+
- Docker (optional, for containerized development)
|
|
164
|
+
|
|
165
|
+
## Development
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
# Clone and install for development
|
|
169
|
+
git clone git@github.com:bemade/odoo-dev.git
|
|
170
|
+
cd odoo-dev
|
|
171
|
+
uv sync
|
|
172
|
+
|
|
173
|
+
# Run tests
|
|
174
|
+
uv run pytest # All tests
|
|
175
|
+
uv run pytest -m "not slow" # Fast tests only
|
|
176
|
+
|
|
177
|
+
# Build
|
|
178
|
+
uv build
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## License
|
|
182
|
+
|
|
183
|
+
LGPL-3. For complete license terms, visit https://www.gnu.org/licenses/lgpl-3.0.en.html
|
odoo_dev-0.3.3/README.md
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# odoo-dev
|
|
2
|
+
|
|
3
|
+
A CLI tool for managing Odoo development environments. Handles local Python setup, Docker containers, database operations, and more.
|
|
4
|
+
|
|
5
|
+
It is the successor to the older `odoo-deploy` shell scripts — if you have notes for `odoo-deploy`, the rough mapping is: `odoo-dev docker start/stop/build` replaces the old `odoo-dev.sh start/stop/build`, and `odoo-dev run`/`test`/`shell` give you a local (venv-based) workflow that `odoo-deploy` didn't.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Install with uv (recommended) — installs the published package from PyPI
|
|
11
|
+
uv tool install odoo-dev
|
|
12
|
+
|
|
13
|
+
# Or with pip
|
|
14
|
+
pip install odoo-dev
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Then make sure the install location is on your `PATH` (uv prints the path; usually `~/.local/bin`):
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
uv tool update-shell # or: export PATH="$HOME/.local/bin:$PATH"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# In your Odoo project directory
|
|
27
|
+
cd my-odoo-project
|
|
28
|
+
|
|
29
|
+
# Full setup: clone Odoo repos, create venv, install deps, configure VSCode
|
|
30
|
+
odoo-dev setup
|
|
31
|
+
|
|
32
|
+
# Or for community edition only
|
|
33
|
+
odoo-dev setup --community
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`setup` reads `ODOO_VERSION` / `PYTHON_VERSION` from a `.env` in the project root (or
|
|
37
|
+
prompts for them and offers to save). It then clones the Odoo repos, builds a `.venv`,
|
|
38
|
+
installs system dependencies, and generates `conf/odoo.conf`. It will offer to set up
|
|
39
|
+
Docker at the end — answer "no" if you only want the local venv workflow.
|
|
40
|
+
|
|
41
|
+
## Database setup (read this before your first `run`/`test`)
|
|
42
|
+
|
|
43
|
+
The generated `conf/odoo.conf` connects as PostgreSQL user **`odoo`** over the local
|
|
44
|
+
socket. You need a running PostgreSQL server and a matching role. `setup` installs
|
|
45
|
+
PostgreSQL but does **not** start it or create the role, so on a fresh machine do this
|
|
46
|
+
once:
|
|
47
|
+
|
|
48
|
+
**macOS (Homebrew):**
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
brew services start postgresql@18 # start the server (use your installed version)
|
|
52
|
+
createuser -s odoo # create the role odoo.conf expects
|
|
53
|
+
# Homebrew's versioned postgres is keg-only; add its bin to PATH if psql/createuser aren't found:
|
|
54
|
+
# export PATH="$(brew --prefix postgresql@18)/bin:$PATH"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Debian/Ubuntu:**
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
sudo systemctl start postgresql
|
|
61
|
+
sudo -u postgres createuser -s odoo
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
You can change the DB user/password in `conf/odoo.conf` if you prefer a different role.
|
|
65
|
+
|
|
66
|
+
## Commands
|
|
67
|
+
|
|
68
|
+
### Local Development (default)
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
odoo-dev run # Start Odoo locally (default port 8069)
|
|
72
|
+
odoo-dev run -d mydb -p 8070 # Pick a database and HTTP port
|
|
73
|
+
odoo-dev run -d mydb -i base # Initialize module(s) on start
|
|
74
|
+
odoo-dev run -d mydb --dev reload # With hot reload
|
|
75
|
+
odoo-dev run --debug # With debugpy (VSCode attach on 5678)
|
|
76
|
+
odoo-dev shell mydb # Open an Odoo shell
|
|
77
|
+
odoo-dev update base -d mydb # Update modules
|
|
78
|
+
odoo-dev test my_module # Run a module's tests (coverage on by default)
|
|
79
|
+
odoo-dev test my_module --test-tags my_module --no-coverage
|
|
80
|
+
odoo-dev test # Auto-discover & test all addons in addons/
|
|
81
|
+
odoo-dev scaffold my_module # Create a new module
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
> Note: the HTTP port flag is `-p` / `--port` (not `--http-port`).
|
|
85
|
+
|
|
86
|
+
### Database Operations
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
odoo-dev db list # List databases
|
|
90
|
+
odoo-dev db restore backup.zip # Restore from backup (neutralized by default)
|
|
91
|
+
odoo-dev db restore backup.zip mydb --no-neutralize
|
|
92
|
+
odoo-dev db drop mydb # Drop database
|
|
93
|
+
odoo-dev db neutralize mydb # Disable emails/crons
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Docker (optional)
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
odoo-dev docker start # Start containers
|
|
100
|
+
odoo-dev docker stop # Stop containers
|
|
101
|
+
odoo-dev docker restart # Restart containers
|
|
102
|
+
odoo-dev docker logs # View logs
|
|
103
|
+
odoo-dev docker build # Rebuild image
|
|
104
|
+
odoo-dev docker shell mydb # Shell in container
|
|
105
|
+
odoo-dev docker psql # PostgreSQL shell
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Setup Commands
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
odoo-dev setup # Full setup
|
|
112
|
+
odoo-dev setup --community # Community edition only
|
|
113
|
+
odoo-dev setup-venv # Just create the venv (no repo clone)
|
|
114
|
+
odoo-dev vscode # Configure VSCode debugging
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Project Structure
|
|
118
|
+
|
|
119
|
+
odoo-dev expects this project structure:
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
my-odoo-project/
|
|
123
|
+
├── .env # Optional: ODOO_VERSION, PYTHON_VERSION
|
|
124
|
+
├── addons/ # Your custom addons
|
|
125
|
+
├── requirements.txt # Project-specific Python deps
|
|
126
|
+
├── odoo/ # Cloned by setup
|
|
127
|
+
├── enterprise/ # Cloned by setup (unless --community)
|
|
128
|
+
├── design-themes/ # Cloned by setup
|
|
129
|
+
├── .venv/ # Created by setup
|
|
130
|
+
└── conf/
|
|
131
|
+
└── odoo.conf # Created by setup
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Configuration
|
|
135
|
+
|
|
136
|
+
Create a `.env` file in your project root:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
ODOO_VERSION=19.0
|
|
140
|
+
PYTHON_VERSION=3.12
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Requirements
|
|
144
|
+
|
|
145
|
+
- Python 3.12+
|
|
146
|
+
- uv (recommended) or pip
|
|
147
|
+
- Git
|
|
148
|
+
- PostgreSQL (for local development — server + an `odoo` role; see "Database setup")
|
|
149
|
+
- Docker (optional, for containerized development)
|
|
150
|
+
|
|
151
|
+
## Development
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
# Clone and install for development
|
|
155
|
+
git clone git@github.com:bemade/odoo-dev.git
|
|
156
|
+
cd odoo-dev
|
|
157
|
+
uv sync
|
|
158
|
+
|
|
159
|
+
# Run tests
|
|
160
|
+
uv run pytest # All tests
|
|
161
|
+
uv run pytest -m "not slow" # Fast tests only
|
|
162
|
+
|
|
163
|
+
# Build
|
|
164
|
+
uv build
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## License
|
|
168
|
+
|
|
169
|
+
LGPL-3. For complete license terms, visit https://www.gnu.org/licenses/lgpl-3.0.en.html
|
|
@@ -480,28 +480,35 @@ def _drop_database(cfg, db_name: str) -> None:
|
|
|
480
480
|
venv_python = cfg.venv_path / "bin" / "python"
|
|
481
481
|
|
|
482
482
|
# Try odoo-bin db drop first
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
483
|
+
try:
|
|
484
|
+
result = subprocess.run(
|
|
485
|
+
[
|
|
486
|
+
str(venv_python),
|
|
487
|
+
str(cfg.odoo_bin),
|
|
488
|
+
"-c",
|
|
489
|
+
str(cfg.config_file),
|
|
490
|
+
"db",
|
|
491
|
+
"drop",
|
|
492
|
+
db_name,
|
|
493
|
+
],
|
|
494
|
+
capture_output=True,
|
|
495
|
+
text=True,
|
|
496
|
+
)
|
|
497
|
+
if result.returncode == 0:
|
|
498
|
+
return
|
|
499
|
+
except OSError:
|
|
500
|
+
pass
|
|
498
501
|
|
|
499
502
|
# Fallback to dropdb
|
|
500
|
-
warning(
|
|
503
|
+
warning("odoo-bin db drop failed, falling back to dropdb...")
|
|
501
504
|
from odoo_dev.commands.db import _parse_db_config
|
|
502
505
|
|
|
503
506
|
db_config = _parse_db_config(cfg.config_file)
|
|
504
507
|
env = {**os.environ, "PGPASSWORD": db_config["password"]}
|
|
508
|
+
|
|
509
|
+
# Terminate active connections first — dropdb will fail if any remain
|
|
510
|
+
_terminate_connections(db_name, db_config)
|
|
511
|
+
|
|
505
512
|
result = subprocess.run(
|
|
506
513
|
[
|
|
507
514
|
"dropdb",
|
|
@@ -521,6 +528,25 @@ def _drop_database(cfg, db_name: str) -> None:
|
|
|
521
528
|
warning(result.stderr.strip())
|
|
522
529
|
|
|
523
530
|
|
|
531
|
+
def _terminate_connections(db_name: str, db_config: dict[str, str]) -> None:
|
|
532
|
+
"""Terminate all active connections to a database."""
|
|
533
|
+
env = {**os.environ, "PGPASSWORD": db_config["password"]}
|
|
534
|
+
subprocess.run(
|
|
535
|
+
[
|
|
536
|
+
"psql",
|
|
537
|
+
"-h", db_config["host"],
|
|
538
|
+
"-p", db_config["port"],
|
|
539
|
+
"-U", db_config["user"],
|
|
540
|
+
"-d", "postgres",
|
|
541
|
+
"-c",
|
|
542
|
+
f"SELECT pg_terminate_backend(pid) FROM pg_stat_activity "
|
|
543
|
+
f"WHERE datname = '{db_name}' AND pid <> pg_backend_pid()",
|
|
544
|
+
],
|
|
545
|
+
capture_output=True,
|
|
546
|
+
text=True,
|
|
547
|
+
env=env,
|
|
548
|
+
)
|
|
549
|
+
|
|
524
550
|
def _get_addons_path(config_file) -> str:
|
|
525
551
|
"""Extract addons_path from odoo.conf."""
|
|
526
552
|
for line in config_file.read_text().splitlines():
|
|
@@ -98,18 +98,6 @@ def setup(
|
|
|
98
98
|
"--clean",
|
|
99
99
|
help="Clean up before setup (remove existing venv, etc.)",
|
|
100
100
|
),
|
|
101
|
-
db_user: str = typer.Option(
|
|
102
|
-
"odoo",
|
|
103
|
-
"-u",
|
|
104
|
-
"--db-user",
|
|
105
|
-
help="Database user for odoo.conf",
|
|
106
|
-
),
|
|
107
|
-
master_password: str = typer.Option(
|
|
108
|
-
"admin",
|
|
109
|
-
"-w",
|
|
110
|
-
"--master-password",
|
|
111
|
-
help="Master (admin) password for odoo.conf",
|
|
112
|
-
),
|
|
113
101
|
) -> None:
|
|
114
102
|
"""Complete setup: clone Odoo repos, configure VSCode, build image."""
|
|
115
103
|
# Prompt for versions if not configured
|
|
@@ -138,13 +126,13 @@ def setup(
|
|
|
138
126
|
warning(
|
|
139
127
|
f"This will install system dependencies and Python {cfg.python_version} if needed"
|
|
140
128
|
)
|
|
141
|
-
setup_venv(
|
|
129
|
+
setup_venv()
|
|
142
130
|
|
|
143
131
|
# Prompt for Docker setup
|
|
144
132
|
warning("\nDo you want to set up the Docker environment?")
|
|
145
133
|
if typer.confirm("Continue with Docker setup?", default=True):
|
|
146
134
|
# Set up Docker files first
|
|
147
|
-
_setup_docker_files(cfg, community_only=community
|
|
135
|
+
_setup_docker_files(cfg, community_only=community)
|
|
148
136
|
|
|
149
137
|
success("\nBuilding Docker image...")
|
|
150
138
|
from odoo_dev.commands.docker import build
|
|
@@ -159,25 +147,15 @@ def setup(
|
|
|
159
147
|
success(" - Debug with VSCode: Use the configured launch profiles")
|
|
160
148
|
|
|
161
149
|
|
|
162
|
-
def setup_venv(
|
|
163
|
-
db_user: str = typer.Option(
|
|
164
|
-
"odoo",
|
|
165
|
-
"-u",
|
|
166
|
-
"--db-user",
|
|
167
|
-
help="Database user for odoo.conf",
|
|
168
|
-
),
|
|
169
|
-
master_password: str = typer.Option(
|
|
170
|
-
"admin",
|
|
171
|
-
"-w",
|
|
172
|
-
"--master-password",
|
|
173
|
-
help="Master (admin) password for odoo.conf",
|
|
174
|
-
),
|
|
175
|
-
) -> None:
|
|
150
|
+
def setup_venv() -> None:
|
|
176
151
|
"""Set up local Python virtual environment for development."""
|
|
177
152
|
cfg = load_config()
|
|
178
153
|
|
|
154
|
+
# Initialize submodules before anything else
|
|
155
|
+
_init_submodules(cfg)
|
|
156
|
+
|
|
179
157
|
# Create config file first
|
|
180
|
-
_setup_odoo_config(cfg
|
|
158
|
+
_setup_odoo_config(cfg)
|
|
181
159
|
|
|
182
160
|
success(f"Setting up Python virtual environment for Odoo {cfg.odoo_version}...")
|
|
183
161
|
|
|
@@ -242,49 +220,6 @@ def setup_venv(
|
|
|
242
220
|
[*venv_pip, "pytest", "pytest-odoo", "debugpy", "manifestoo", "coverage"]
|
|
243
221
|
)
|
|
244
222
|
|
|
245
|
-
# Install Python external dependencies declared in addon manifests (runtime + test)
|
|
246
|
-
if cfg.addons_dir.is_dir():
|
|
247
|
-
success("Installing addon Python dependencies from manifests...")
|
|
248
|
-
venv_python = cfg.venv_path / "bin" / "python"
|
|
249
|
-
# Runtime deps via manifestoo
|
|
250
|
-
result = subprocess.run(
|
|
251
|
-
[
|
|
252
|
-
str(venv_python),
|
|
253
|
-
"-m",
|
|
254
|
-
"manifestoo",
|
|
255
|
-
"--select-addons-dir",
|
|
256
|
-
str(cfg.addons_dir),
|
|
257
|
-
"list-external-dependencies",
|
|
258
|
-
"python",
|
|
259
|
-
],
|
|
260
|
-
capture_output=True,
|
|
261
|
-
text=True,
|
|
262
|
-
env={**os.environ, "ODOO_VERSION": "", "ODOO_SERIES": ""},
|
|
263
|
-
)
|
|
264
|
-
all_python_deps: set[str] = set(result.stdout.split())
|
|
265
|
-
# Test deps via direct manifest scan (manifestoo doesn't read test_external_dependencies)
|
|
266
|
-
import ast
|
|
267
|
-
for manifest_path in cfg.addons_dir.glob("*/__manifest__.py"):
|
|
268
|
-
try:
|
|
269
|
-
manifest = ast.literal_eval(manifest_path.read_text())
|
|
270
|
-
test_deps = manifest.get("test_external_dependencies", {}).get("python", [])
|
|
271
|
-
all_python_deps.update(test_deps)
|
|
272
|
-
except Exception:
|
|
273
|
-
pass
|
|
274
|
-
python_deps = " ".join(all_python_deps)
|
|
275
|
-
if python_deps:
|
|
276
|
-
subprocess.run(
|
|
277
|
-
[
|
|
278
|
-
"uv",
|
|
279
|
-
"pip",
|
|
280
|
-
"install",
|
|
281
|
-
"--python",
|
|
282
|
-
str(venv_python),
|
|
283
|
-
*python_deps.split(),
|
|
284
|
-
],
|
|
285
|
-
check=False,
|
|
286
|
-
)
|
|
287
|
-
|
|
288
223
|
success("\nVirtual environment setup complete!")
|
|
289
224
|
success(f"To activate: source {cfg.venv_path}/bin/activate")
|
|
290
225
|
|
|
@@ -341,7 +276,7 @@ def _init_submodules(cfg) -> None:
|
|
|
341
276
|
warning(f"Submodule initialization had issues: {result.stderr}")
|
|
342
277
|
|
|
343
278
|
|
|
344
|
-
def _setup_odoo_config(cfg, community_only: bool = False
|
|
279
|
+
def _setup_odoo_config(cfg, community_only: bool = False) -> None:
|
|
345
280
|
"""Create odoo.conf configuration file."""
|
|
346
281
|
conf_dir = cfg.project_dir / "conf"
|
|
347
282
|
conf_file = conf_dir / "odoo.conf"
|
|
@@ -376,8 +311,8 @@ def _setup_odoo_config(cfg, community_only: bool = False, db_user: str = "odoo",
|
|
|
376
311
|
|
|
377
312
|
config_content = f"""[options]
|
|
378
313
|
addons_path = {",".join(addons_paths)}
|
|
379
|
-
admin_passwd =
|
|
380
|
-
db_user =
|
|
314
|
+
admin_passwd = admin
|
|
315
|
+
db_user = odoo
|
|
381
316
|
db_password = odoo
|
|
382
317
|
"""
|
|
383
318
|
|
|
@@ -386,7 +321,7 @@ db_password = odoo
|
|
|
386
321
|
success(f"Config file created at {conf_file}")
|
|
387
322
|
|
|
388
323
|
|
|
389
|
-
def _setup_docker_files(cfg, community_only: bool = False
|
|
324
|
+
def _setup_docker_files(cfg, community_only: bool = False) -> None:
|
|
390
325
|
"""Copy Docker templates to .odoo-deploy directory."""
|
|
391
326
|
success("Setting up Docker files...")
|
|
392
327
|
|
|
@@ -406,10 +341,10 @@ def _setup_docker_files(cfg, community_only: bool = False, db_user: str = "odoo"
|
|
|
406
341
|
success(f"Copied {filename}")
|
|
407
342
|
|
|
408
343
|
# Create Docker odoo.conf
|
|
409
|
-
_setup_docker_odoo_config(cfg, community_only=community_only
|
|
344
|
+
_setup_docker_odoo_config(cfg, community_only=community_only)
|
|
410
345
|
|
|
411
346
|
|
|
412
|
-
def _generate_docker_odoo_conf(community_only: bool = False
|
|
347
|
+
def _generate_docker_odoo_conf(community_only: bool = False) -> str:
|
|
413
348
|
"""Generate Docker-specific odoo.conf content."""
|
|
414
349
|
# Build addons path for Docker (using /opt/project paths)
|
|
415
350
|
addons_paths = [
|
|
@@ -430,10 +365,10 @@ def _generate_docker_odoo_conf(community_only: bool = False, db_user: str = "odo
|
|
|
430
365
|
|
|
431
366
|
return f"""[options]
|
|
432
367
|
addons_path = {",".join(addons_paths)}
|
|
433
|
-
admin_passwd =
|
|
368
|
+
admin_passwd = admin
|
|
434
369
|
db_host = db
|
|
435
370
|
db_port = 5432
|
|
436
|
-
db_user =
|
|
371
|
+
db_user = odoo
|
|
437
372
|
db_password = odoo
|
|
438
373
|
http_port = 8069
|
|
439
374
|
gevent_port = 8072
|
|
@@ -451,7 +386,7 @@ data_dir = /opt/odoo-filestore
|
|
|
451
386
|
"""
|
|
452
387
|
|
|
453
388
|
|
|
454
|
-
def _setup_docker_odoo_config(cfg, community_only: bool = False
|
|
389
|
+
def _setup_docker_odoo_config(cfg, community_only: bool = False) -> None:
|
|
455
390
|
"""Create Docker-specific odoo.conf configuration file."""
|
|
456
391
|
conf_file = cfg.docker_config_file
|
|
457
392
|
|
|
@@ -460,7 +395,7 @@ def _setup_docker_odoo_config(cfg, community_only: bool = False, db_user: str =
|
|
|
460
395
|
return
|
|
461
396
|
|
|
462
397
|
success("Creating Docker Odoo configuration file...")
|
|
463
|
-
conf_file.write_text(_generate_docker_odoo_conf(community_only=community_only
|
|
398
|
+
conf_file.write_text(_generate_docker_odoo_conf(community_only=community_only))
|
|
464
399
|
conf_file.chmod(0o600)
|
|
465
400
|
success(f"Docker config file created at {conf_file}")
|
|
466
401
|
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"""Integration tests for _drop_database.
|
|
2
|
+
|
|
3
|
+
These tests verify that test databases are actually dropped after a test run.
|
|
4
|
+
Requires a local PostgreSQL instance accessible via peer authentication.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import subprocess
|
|
8
|
+
import time
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
import pytest
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _pg_run(cmd: list[str], **kwargs) -> subprocess.CompletedProcess:
|
|
16
|
+
"""Run a PostgreSQL command using peer auth on the local socket."""
|
|
17
|
+
return subprocess.run(cmd, capture_output=True, text=True, **kwargs)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _db_exists(db_name: str) -> bool:
|
|
21
|
+
result = _pg_run(["psql", "-d", "postgres", "-tAc",
|
|
22
|
+
f"SELECT 1 FROM pg_database WHERE datname = '{db_name}'"])
|
|
23
|
+
return result.stdout.strip() == "1"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _create_db(db_name: str) -> None:
|
|
27
|
+
result = _pg_run(["createdb", db_name])
|
|
28
|
+
assert result.returncode == 0, f"createdb failed: {result.stderr}"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _drop_db_force(db_name: str) -> None:
|
|
32
|
+
"""Forcefully drop a database (for test cleanup)."""
|
|
33
|
+
_pg_run(["psql", "-d", "postgres", "-c",
|
|
34
|
+
f"DROP DATABASE IF EXISTS \"{db_name}\" WITH (FORCE)"])
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass
|
|
38
|
+
class FakeConfig:
|
|
39
|
+
"""Minimal config to satisfy _drop_database's interface."""
|
|
40
|
+
project_dir: Path
|
|
41
|
+
venv_path: Path
|
|
42
|
+
odoo_bin: Path
|
|
43
|
+
config_file: Path
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _make_config(tmp_path: Path) -> FakeConfig:
|
|
47
|
+
"""Create a fake config with an odoo.conf using peer auth.
|
|
48
|
+
|
|
49
|
+
Sets up a real python symlink but a fake odoo-bin that always exits 1,
|
|
50
|
+
so the odoo-bin drop method fails cleanly (nonzero exit) and the
|
|
51
|
+
dropdb fallback path is exercised — matching real-world behavior where
|
|
52
|
+
'odoo-bin db drop' fails.
|
|
53
|
+
"""
|
|
54
|
+
conf = tmp_path / "conf"
|
|
55
|
+
conf.mkdir()
|
|
56
|
+
config_file = conf / "odoo.conf"
|
|
57
|
+
# Use peer auth (no password, local socket) matching the test environment
|
|
58
|
+
config_file.write_text(
|
|
59
|
+
"[options]\n"
|
|
60
|
+
"db_host = /var/run/postgresql\n"
|
|
61
|
+
"db_port = 5432\n"
|
|
62
|
+
f"db_user = {subprocess.run(['whoami'], capture_output=True, text=True).stdout.strip()}\n"
|
|
63
|
+
"db_password =\n"
|
|
64
|
+
)
|
|
65
|
+
# Create a venv with a real python and a fake odoo-bin that always fails
|
|
66
|
+
venv_path = tmp_path / ".venv"
|
|
67
|
+
venv_path.mkdir()
|
|
68
|
+
bin_dir = venv_path / "bin"
|
|
69
|
+
bin_dir.mkdir()
|
|
70
|
+
import sys
|
|
71
|
+
(bin_dir / "python").symlink_to(sys.executable)
|
|
72
|
+
|
|
73
|
+
fake_odoo_bin = tmp_path / "odoo-bin"
|
|
74
|
+
fake_odoo_bin.write_text("#!/usr/bin/env python3\nimport sys; sys.exit(1)\n")
|
|
75
|
+
fake_odoo_bin.chmod(0o755)
|
|
76
|
+
|
|
77
|
+
return FakeConfig(
|
|
78
|
+
project_dir=tmp_path,
|
|
79
|
+
venv_path=venv_path,
|
|
80
|
+
odoo_bin=fake_odoo_bin,
|
|
81
|
+
config_file=config_file,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@pytest.mark.slow
|
|
86
|
+
class TestDropDatabase:
|
|
87
|
+
"""Verify _drop_database actually removes the database."""
|
|
88
|
+
|
|
89
|
+
def _unique_db(self) -> str:
|
|
90
|
+
return f"test_odoodev_{int(time.time() * 1000)}"
|
|
91
|
+
|
|
92
|
+
def test_drop_removes_database(self, tmp_path: Path):
|
|
93
|
+
"""Basic case: database with no active connections is dropped."""
|
|
94
|
+
from odoo_dev.commands.run import _drop_database
|
|
95
|
+
|
|
96
|
+
db_name = self._unique_db()
|
|
97
|
+
cfg = _make_config(tmp_path)
|
|
98
|
+
|
|
99
|
+
_create_db(db_name)
|
|
100
|
+
assert _db_exists(db_name), "Precondition: database should exist"
|
|
101
|
+
|
|
102
|
+
try:
|
|
103
|
+
_drop_database(cfg, db_name)
|
|
104
|
+
assert not _db_exists(db_name), (
|
|
105
|
+
f"Database {db_name} still exists after _drop_database!"
|
|
106
|
+
)
|
|
107
|
+
finally:
|
|
108
|
+
_drop_db_force(db_name)
|
|
109
|
+
|
|
110
|
+
def test_drop_works_when_venv_missing(self, tmp_path: Path):
|
|
111
|
+
"""When venv python doesn't exist, should fall back to dropdb
|
|
112
|
+
instead of crashing with FileNotFoundError."""
|
|
113
|
+
from odoo_dev.commands.run import _drop_database
|
|
114
|
+
|
|
115
|
+
db_name = self._unique_db()
|
|
116
|
+
cfg = _make_config(tmp_path)
|
|
117
|
+
# Remove the python symlink to simulate missing venv
|
|
118
|
+
(cfg.venv_path / "bin" / "python").unlink()
|
|
119
|
+
|
|
120
|
+
_create_db(db_name)
|
|
121
|
+
assert _db_exists(db_name), "Precondition: database should exist"
|
|
122
|
+
|
|
123
|
+
try:
|
|
124
|
+
_drop_database(cfg, db_name)
|
|
125
|
+
assert not _db_exists(db_name), (
|
|
126
|
+
f"Database {db_name} still exists after _drop_database!"
|
|
127
|
+
)
|
|
128
|
+
finally:
|
|
129
|
+
_drop_db_force(db_name)
|
|
130
|
+
|
|
131
|
+
def test_drop_removes_database_with_active_connections(self, tmp_path: Path):
|
|
132
|
+
"""Simulates a lingering Odoo worker holding a connection open.
|
|
133
|
+
|
|
134
|
+
This is the primary failure mode: dropdb refuses to drop a database
|
|
135
|
+
that has active connections, and _drop_database doesn't terminate
|
|
136
|
+
them first.
|
|
137
|
+
"""
|
|
138
|
+
from odoo_dev.commands.run import _drop_database
|
|
139
|
+
|
|
140
|
+
db_name = self._unique_db()
|
|
141
|
+
cfg = _make_config(tmp_path)
|
|
142
|
+
|
|
143
|
+
_create_db(db_name)
|
|
144
|
+
assert _db_exists(db_name), "Precondition: database should exist"
|
|
145
|
+
|
|
146
|
+
# Hold an active connection (simulates a lingering Odoo worker)
|
|
147
|
+
blocker = subprocess.Popen(
|
|
148
|
+
["psql", "-d", db_name, "-c", "SELECT pg_sleep(300)"],
|
|
149
|
+
stdout=subprocess.PIPE,
|
|
150
|
+
stderr=subprocess.PIPE,
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
try:
|
|
154
|
+
# Give the connection a moment to establish
|
|
155
|
+
time.sleep(0.5)
|
|
156
|
+
|
|
157
|
+
_drop_database(cfg, db_name)
|
|
158
|
+
assert not _db_exists(db_name), (
|
|
159
|
+
f"Database {db_name} still exists after _drop_database! "
|
|
160
|
+
"Active connections were not terminated before drop."
|
|
161
|
+
)
|
|
162
|
+
finally:
|
|
163
|
+
blocker.terminate()
|
|
164
|
+
blocker.wait(timeout=5)
|
|
165
|
+
_drop_db_force(db_name)
|
|
@@ -158,6 +158,56 @@ class TestSetupDockerFiles:
|
|
|
158
158
|
assert cfg.docker_config_file.read_text() == "existing config"
|
|
159
159
|
|
|
160
160
|
|
|
161
|
+
class TestInitSubmodules:
|
|
162
|
+
"""Test _init_submodules is called correctly from setup_venv."""
|
|
163
|
+
|
|
164
|
+
def test_setup_venv_calls_init_submodules(self, tmp_path: Path):
|
|
165
|
+
"""setup_venv should initialize submodules before setting up the venv."""
|
|
166
|
+
from unittest.mock import call, patch
|
|
167
|
+
|
|
168
|
+
cfg = _make_cfg(tmp_path)
|
|
169
|
+
# Create .gitmodules to trigger the submodule check
|
|
170
|
+
(tmp_path / ".gitmodules").write_text("[submodule]\n")
|
|
171
|
+
|
|
172
|
+
with patch("odoo_dev.commands.setup.load_config", return_value=cfg), \
|
|
173
|
+
patch("odoo_dev.commands.setup._init_submodules") as mock_init, \
|
|
174
|
+
patch("odoo_dev.commands.setup._setup_odoo_config"), \
|
|
175
|
+
patch("odoo_dev.commands.setup._install_system_dependencies"), \
|
|
176
|
+
patch("odoo_dev.commands.setup._update_python_path"), \
|
|
177
|
+
patch("subprocess.run", return_value=type("R", (), {"returncode": 0})()):
|
|
178
|
+
from odoo_dev.commands.setup import setup_venv
|
|
179
|
+
setup_venv()
|
|
180
|
+
|
|
181
|
+
mock_init.assert_called_once_with(cfg)
|
|
182
|
+
|
|
183
|
+
def test_init_submodules_skips_if_no_gitmodules(self, tmp_path: Path):
|
|
184
|
+
"""_init_submodules should do nothing if .gitmodules does not exist."""
|
|
185
|
+
from odoo_dev.commands.setup import _init_submodules
|
|
186
|
+
|
|
187
|
+
cfg = _make_cfg(tmp_path)
|
|
188
|
+
with patch("subprocess.run") as mock_run:
|
|
189
|
+
_init_submodules(cfg)
|
|
190
|
+
mock_run.assert_not_called()
|
|
191
|
+
|
|
192
|
+
def test_init_submodules_runs_git_command(self, tmp_path: Path):
|
|
193
|
+
"""_init_submodules should run git submodule update when .gitmodules exists."""
|
|
194
|
+
from odoo_dev.commands.setup import _init_submodules
|
|
195
|
+
|
|
196
|
+
cfg = _make_cfg(tmp_path)
|
|
197
|
+
(tmp_path / ".gitmodules").write_text("[submodule]\n")
|
|
198
|
+
|
|
199
|
+
with patch("subprocess.run", return_value=type("R", (), {"returncode": 0, "stderr": ""})()) as mock_run:
|
|
200
|
+
_init_submodules(cfg)
|
|
201
|
+
|
|
202
|
+
mock_run.assert_called_once()
|
|
203
|
+
args = mock_run.call_args[0][0]
|
|
204
|
+
assert "git" in args
|
|
205
|
+
assert "submodule" in args
|
|
206
|
+
assert "update" in args
|
|
207
|
+
assert "--init" in args
|
|
208
|
+
assert "--recursive" in args
|
|
209
|
+
|
|
210
|
+
|
|
161
211
|
class TestVscodeSetup:
|
|
162
212
|
"""Test vscode() copies templates correctly."""
|
|
163
213
|
|
odoo_dev-0.3.1/PKG-INFO
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: odoo-dev
|
|
3
|
-
Version: 0.3.1
|
|
4
|
-
Summary: Odoo Development Environment Helper
|
|
5
|
-
Project-URL: Homepage, https://git.bemade.org/bemade/odoo-dev
|
|
6
|
-
Project-URL: Repository, https://git.bemade.org/bemade/odoo-dev
|
|
7
|
-
Project-URL: Issues, https://git.bemade.org/bemade/odoo-dev/-/issues
|
|
8
|
-
License-Expression: LGPL-3.0
|
|
9
|
-
Requires-Python: >=3.12
|
|
10
|
-
Requires-Dist: pyyaml>=6.0
|
|
11
|
-
Requires-Dist: rich>=13.0.0
|
|
12
|
-
Requires-Dist: typer>=0.9.0
|
|
13
|
-
Description-Content-Type: text/markdown
|
|
14
|
-
|
|
15
|
-
# odoo-dev
|
|
16
|
-
|
|
17
|
-
> **This repository has moved to GitHub: https://github.com/bemade/odoo-dev**
|
|
18
|
-
>
|
|
19
|
-
> This GitLab repository is archived and no longer maintained.
|
odoo_dev-0.3.1/README.md
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
gitdir: ../../../.git/modules/tests/fixtures/odoo-empty
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|