Merge branch 'develop'

- Integrate Selenium
- Fix npm installation
- Support osx to open_terminal
- Improve Pycharm script
- Support default configuration Pycharm
- Change format script to reduce test error (but cause others
problems...)
- FAQ error git bind, kill git-daemon
- rename erplibre_workspace/it to erplibre_devops
- upgrade docker version buster to bullseye
This commit is contained in:
Mathieu Benoit 2023-12-02 14:26:30 -05:00
commit 6c66f36be5
36 changed files with 1124 additions and 244 deletions

20
.editorconfig Normal file
View file

@ -0,0 +1,20 @@
# Configuration for known file extensions
[*.{css,js,json,less,md,py,rst,sass,scss,xml,yaml,yml}]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[.eslintrc,*.{json,yml,yaml,rst,md}]
indent_size = 2
# Do not configure editor for libs and autogenerated content
[*/static/{lib,src/lib}/**,*/static/description/index.html,*/readme/../README.rst]
charset = unset
end_of_line = unset
indent_size = unset
indent_style = unset
insert_final_newline = false
trim_trailing_whitespace = false

2
.gitignore vendored
View file

@ -24,3 +24,5 @@ get-poetry.py
artifacts
wkhtmltox*
cache
node_modules

View file

@ -7,6 +7,23 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## Added
- Selenium script to increase open software client interface and automated some actions.
- FAQ about kill git-daemon
## Changed
- Guide to move dev to prod
- Update docker buster to bullseye
- Improve format script to help code-generator
- Improve PyCharm script
- Support OSX for open-terminal
### Fixed
- NPM installation locally and not globally
## [1.5.0] - 2023-07-07
**Migration note**

View file

@ -1,27 +1,31 @@
name,script_path,parameters,folder
run,./odoo/odoo-bin,--limit-time-real 999999 -c config.conf,run
run_parallel_test,./script/test/run_parallel_test.py,,test
cg_cg,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_code_generator,code_generator
cg_cg_template,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_code_generator,code_generator_template
code_generator_auto_backup,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_auto_backup,code_generator
code_generator_demo,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo,code_generator
code_generator_demo_export_helpdesk,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_export_helpdesk,code_generator
code_generator_demo_export_website,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_export_website,code_generator
code_generator_demo_export_website_attachments,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_export_website_attachments,code_generator
code_generator_demo_internal,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_internal,code_generator
code_generator_demo_internal_inherit,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_internal_inherit,code_generator
code_generator_demo_mariadb_sql_example_1,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_mariadb_sql_example_1,code_generator
code_generator_demo_portal,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_portal,code_generator
code_generator_demo_theme_website,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_theme_website,code_generator
code_generator_demo_website_leaflet,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_website_leaflet,code_generator
code_generator_demo_website_multiple_snippet,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_website_multiple_snippet,code_generator
code_generator_demo_website_snippet,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_website_snippet,code_generator
code_generator_migrator_demo_mariadb_sql_example_1,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_migrator_demo_mariadb_sql_example_1,code_generator_migrator
code_generator_template_demo_internal,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_demo_internal,code_generator_template
code_generator_template_demo_internal_inherit,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_demo_internal_inherit,code_generator_template
code_generator_template_demo_mariadb_sql_example_1,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_demo_mariadb_sql_example_1,code_generator_template
code_generator_template_demo_portal,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_demo_portal,code_generator_template
code_generator_template_demo_sysadmin_cron,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_demo_sysadmin_cron,code_generator_template
code_generator_template_demo_website_multiple_snippet,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_demo_website_multiple_snippet,code_generator_template
code_generator_template_demo_website_snippet,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_demo_website_snippet,code_generator_template
create demo internal,./script/code_generator/new_project.py,-m demo_internal -d addons/TechnoLibre_odoo-code-generator-template,new cg project
name,script_path,parameters,folder,default
run,./odoo/odoo-bin,--limit-time-real 999999 -c config.conf,run,True
run_parallel_test,./script/test/run_parallel_test.py,,test,
cg_cg,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_code_generator,code_generator,
cg_cg_template,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_code_generator,code_generator_template,
code_generator_auto_backup,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_auto_backup,code_generator,
code_generator_demo,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo,code_generator,
code_generator_demo_export_helpdesk,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_export_helpdesk,code_generator,
code_generator_demo_export_website,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_export_website,code_generator,
code_generator_demo_export_website_attachments,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_export_website_attachments,code_generator,
code_generator_demo_internal,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_internal,code_generator,
code_generator_demo_internal_inherit,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_internal_inherit,code_generator,
code_generator_demo_mariadb_sql_example_1,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_mariadb_sql_example_1,code_generator,
code_generator_demo_portal,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_portal,code_generator,
code_generator_demo_theme_website,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_theme_website,code_generator,
code_generator_demo_website_leaflet,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_website_leaflet,code_generator,
code_generator_demo_website_multiple_snippet,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_website_multiple_snippet,code_generator,
code_generator_demo_website_snippet,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_website_snippet,code_generator,
code_generator_migrator_demo_mariadb_sql_example_1,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_migrator_demo_mariadb_sql_example_1,code_generator_migrator,
code_generator_template_demo_internal,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_demo_internal,code_generator_template,
code_generator_template_demo_internal_inherit,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_demo_internal_inherit,code_generator_template,
code_generator_template_demo_mariadb_sql_example_1,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_demo_mariadb_sql_example_1,code_generator_template,
code_generator_template_demo_portal,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_demo_portal,code_generator_template,
code_generator_template_demo_sysadmin_cron,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_demo_sysadmin_cron,code_generator_template,
code_generator_template_demo_website_multiple_snippet,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_demo_website_multiple_snippet,code_generator_template,
code_generator_template_demo_website_snippet,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_demo_website_snippet,code_generator_template,
create demo internal,./script/code_generator/new_project.py,-m demo_internal -d addons/TechnoLibre_odoo-code-generator-template,new cg project,
run_robotlibre,./odoo/odoo-bin,--limit-time-real 999999 -c config.conf -d robotlibre,robotlibre,
run_robotlibre_update,./odoo/odoo-bin,--limit-time-real 999999 --no-http --stop-after-init --dev cg -d robotlibre -i erplibre_devops -u erplibre_devops,robotlibre,
run_robotlibre_generate,./script/code_generator/new_project.py,-f -d ./addons/ERPLibre_erplibre_addons -m erplibre_devops,robotlibre,

1 name script_path parameters folder default
2 run ./odoo/odoo-bin --limit-time-real 999999 -c config.conf run True
3 run_parallel_test ./script/test/run_parallel_test.py test
4 cg_cg ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_code_generator code_generator
5 cg_cg_template ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_code_generator code_generator_template
6 code_generator_auto_backup ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_auto_backup code_generator
7 code_generator_demo ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo code_generator
8 code_generator_demo_export_helpdesk ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_export_helpdesk code_generator
9 code_generator_demo_export_website ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_export_website code_generator
10 code_generator_demo_export_website_attachments ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_export_website_attachments code_generator
11 code_generator_demo_internal ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_internal code_generator
12 code_generator_demo_internal_inherit ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_internal_inherit code_generator
13 code_generator_demo_mariadb_sql_example_1 ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_mariadb_sql_example_1 code_generator
14 code_generator_demo_portal ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_portal code_generator
15 code_generator_demo_theme_website ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_theme_website code_generator
16 code_generator_demo_website_leaflet ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_website_leaflet code_generator
17 code_generator_demo_website_multiple_snippet ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_website_multiple_snippet code_generator
18 code_generator_demo_website_snippet ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_demo_website_snippet code_generator
19 code_generator_migrator_demo_mariadb_sql_example_1 ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_migrator_demo_mariadb_sql_example_1 code_generator_migrator
20 code_generator_template_demo_internal ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_demo_internal code_generator_template
21 code_generator_template_demo_internal_inherit ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_demo_internal_inherit code_generator_template
22 code_generator_template_demo_mariadb_sql_example_1 ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_demo_mariadb_sql_example_1 code_generator_template
23 code_generator_template_demo_portal ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_demo_portal code_generator_template
24 code_generator_template_demo_sysadmin_cron ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_demo_sysadmin_cron code_generator_template
25 code_generator_template_demo_website_multiple_snippet ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_demo_website_multiple_snippet code_generator_template
26 code_generator_template_demo_website_snippet ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_demo_website_snippet code_generator_template
27 create demo internal ./script/code_generator/new_project.py -m demo_internal -d addons/TechnoLibre_odoo-code-generator-template new cg project
28 run_robotlibre ./odoo/odoo-bin --limit-time-real 999999 -c config.conf -d robotlibre robotlibre
29 run_robotlibre_update ./odoo/odoo-bin --limit-time-real 999999 --no-http --stop-after-init --dev cg -d robotlibre -i erplibre_devops -u erplibre_devops robotlibre
30 run_robotlibre_generate ./script/code_generator/new_project.py -f -d ./addons/ERPLibre_erplibre_addons -m erplibre_devops robotlibre
31

View file

@ -10,3 +10,4 @@ doc/odoo_documentation-user
artifacts
cache
htmlcov
node_modules

View file

@ -85,6 +85,14 @@ git rebase -i HEAD~4 -x "git commit --amend --author 'Author Name <author.name@m
git cherry-pick -m 1 --strategy-option theirs HASH
```
## git update manifest
### Error fatal: unable to allocate any listen sockets on port 9418
```bash
pkill git-daemon
```
## git-repo
### error.GitError fatal bad revision

View file

@ -98,10 +98,14 @@ cd /[EL_USER]/erplibre
## Move prod database to dev
When moving prod database to your dev environment, you want to remove email servers and install user test to test the
database. WARNING, this is not safe for production, you will expose all data. Run:
database. WARNING, this is not safe for production, you will expose all data.
1. Copy your database image to directory image_db, exemple the image name is `my_db.zip`
1. Run
```bash
./script/database/migrate_prod_to_test.sh DATABASE
./script/database/db_restore.py --clean_cache --database test_my_db --image my_db
./script/addons/update_prod_to_dev.sh test_my_db
```
## Update production

View file

@ -1,4 +1,4 @@
FROM python:3.7.16-slim-buster
FROM python:3.7.17-slim-bullseye
MAINTAINER TechnoLibre <docker@technolibre.ca>
SHELL ["/bin/bash", "-xo", "pipefail", "-c"]
@ -27,6 +27,10 @@ RUN apt-get update \
npm \
xz-utils \
git \
tree \
vim \
htop \
tig \
wget \
make \
libssl-dev \
@ -56,8 +60,8 @@ RUN apt-get update \
libncursesw5-dev \
libffi-dev \
uuid-dev \
&& curl -o wkhtmltox.deb -sSL https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.5/wkhtmltox_0.12.5-1.stretch_amd64.deb \
&& echo '7e35a63f9db14f93ec7feeb0fce76b30c08f2057 wkhtmltox.deb' | sha1sum -c - \
&& curl -o wkhtmltox.deb -sSL https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.buster_amd64.deb \
&& echo 'd9f259a67e05e1c221d48b504453645e6c491fab wkhtmltox.deb' | sha1sum -c - \
&& apt-get install -y --no-install-recommends ./wkhtmltox.deb \
&& rm -rf /var/lib/apt/lists/* wkhtmltox.deb

View file

@ -43,6 +43,10 @@ RUN cd $ODOO_PREFIX && \
./.venv/bin/poetry --version && \
./.venv/bin/poetry install
# Install local npm
RUN cd $ODOO_PREFIX && \
npm install
RUN cd $ODOO_PREFIX && \
head /etc/odoo/odoo.conf && \
./docker/repo_manifest_gen_org_prefix_path.py $ODOO_PREFIX/addons /etc/odoo/odoo.conf /etc/odoo/odoo.conf && \

66
package-lock.json generated Normal file
View file

@ -0,0 +1,66 @@
{
"name": "erplibre",
"version": "1.5.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "erplibre",
"version": "1.5.0",
"license": "AGPLv3",
"devDependencies": {
"@prettier/plugin-xml": "==2.2.0",
"prettier": "==2.8.8"
}
},
"node_modules/@prettier/plugin-xml": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@prettier/plugin-xml/-/plugin-xml-2.2.0.tgz",
"integrity": "sha512-UWRmygBsyj4bVXvDiqSccwT1kmsorcwQwaIy30yVh8T+Gspx4OlC0shX1y+ZuwXZvgnafmpRYKks0bAu9urJew==",
"dev": true,
"dependencies": {
"@xml-tools/parser": "^1.0.11",
"prettier": ">=2.4.0"
}
},
"node_modules/@xml-tools/parser": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@xml-tools/parser/-/parser-1.0.11.tgz",
"integrity": "sha512-aKqQ077XnR+oQtHJlrAflaZaL7qZsulWc/i/ZEooar5JiWj1eLt0+Wg28cpa+XLney107wXqneC+oG1IZvxkTA==",
"dev": true,
"dependencies": {
"chevrotain": "7.1.1"
}
},
"node_modules/chevrotain": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-7.1.1.tgz",
"integrity": "sha512-wy3mC1x4ye+O+QkEinVJkPf5u2vsrDIYW9G7ZuwFl6v/Yu0LwUuT2POsb+NUWApebyxfkQq6+yDfRExbnI5rcw==",
"dev": true,
"dependencies": {
"regexp-to-ast": "0.5.0"
}
},
"node_modules/prettier": {
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
"dev": true,
"bin": {
"prettier": "bin-prettier.js"
},
"engines": {
"node": ">=10.13.0"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/regexp-to-ast": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz",
"integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==",
"dev": true
}
}
}

11
package.json Normal file
View file

@ -0,0 +1,11 @@
{
"name": "erplibre",
"description": "Easy installation of Odoo",
"version": "1.5.0",
"license": "AGPLv3",
"homepage": "https://erplibre.ca",
"devDependencies": {
"@prettier/plugin-xml": "==2.2.0",
"prettier": "==2.8.8"
}
}

View file

@ -49,7 +49,17 @@ cd "$3" || exit 1
git checkout -- "*.po*"
cd - || exit 1
./script/maintenance/black.sh "$3"
#./script/maintenance/format.sh "$3"
# Itéré pour chaque module et formater
IFS=','
# Diviser la chaîne en un tableau
read -ra elements <<<"$4"
# Itérer sur les éléments
for element in "${elements[@]}"; do
echo "Format ${3}/${element}"
./script/maintenance/format.sh "${3}/${element}"
done
echo "TEST ${2}"
./script/code_generator/check_git_change_code_generator.sh "$3"
retVal=$?

View file

@ -57,6 +57,11 @@ def get_config():
required=True,
help="Module name to create",
)
parser.add_argument(
"--odoo_config",
default="./config.conf",
help="Odoo config path",
)
parser.add_argument(
"--config",
help="""Configuration to create models with fields and type. JSON style.
@ -116,12 +121,14 @@ class ProjectManagement:
keep_bd_alive=False,
coverage=False,
config="",
odoo_config="./config.conf",
):
self.force = force
self._coverage = coverage
self.keep_bd_alive = keep_bd_alive
self.msg_error = ""
self.has_config_update = False
self.odoo_config = odoo_config
self.module_directory = module_directory
if not os.path.exists(self.module_directory):
@ -522,7 +529,7 @@ class ProjectManagement:
os.system(cmd)
# Validate
if not os.path.exists(template_path):
if not os.path.exists(module_path):
_logger.error(f"Module not exists '{module_path}'")
return False
else:
@ -532,7 +539,7 @@ class ProjectManagement:
def update_config(self):
config = configparser.ConfigParser()
config.read("./config.conf")
config.read(self.odoo_config)
addons_path = config.get("options", "addons_path")
lst_addons_path = addons_path.split(",")
lst_directory = list(
@ -579,6 +586,7 @@ def main():
keep_bd_alive=config.keep_bd_alive,
coverage=config.coverage,
config=config.config,
odoo_config=config.odoo_config,
)
if project.msg_error:
return -1

View file

@ -212,8 +212,8 @@ def main():
with open(hooks_file_path, "w") as source:
source.write(new_file_content)
# Call black
os.system(f"./script/maintenance/black.sh {hooks_file_path}")
# Call format all file
os.system(f"./script/maintenance/format.sh {hooks_file_path}")
return 0

View file

@ -38,7 +38,7 @@ def get_config():
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description="""\
Manipulate configuration for your IDE Pycharm about ERPLibre.
Manipulate configuration for your IDE Pycharm about ERPLibre.
This script manage only Python configuration, other configuration will be ignore.
""",
epilog="""\
@ -65,10 +65,22 @@ def get_config():
action="store_true",
help="Initialize minimum configuration for Pycharm.",
)
parser.add_argument(
"--overwrite",
action="store_true",
help="Remove old data and replace it.",
)
args = parser.parse_args()
if args.init or args.list_configuration or args.list_configuration_full:
if (
args.init
or args.list_configuration
or args.list_configuration_full
or args.overwrite
):
args.configuration = True
if args.overwrite:
args.init = True
else:
args.configuration = False
@ -78,6 +90,7 @@ def get_config():
def main():
has_execute = False
config = get_config()
_logger.info(f"Work on directory {os.getcwd()}")
# TODO modifier vcs.xml pour le mapping des répertoires git
@ -120,6 +133,7 @@ def main():
def read_xml_and_execute(file_name, cb, name, config):
_logger.info(f"Pycharm configuration on file {file_name}")
with open(file_name) as xml:
xml_as_string = xml.read()
dct_project_xml = xmltodict.parse(xml_as_string)
@ -133,8 +147,7 @@ def read_xml_and_execute(file_name, cb, name, config):
xml.write(xml_format)
_logger.info(f"File {file_name} has been write.")
subprocess.call(
"prettier --tab-width 2 --print-width 999999 --write"
f" '{file_name}'",
f"script/maintenance/prettier_xml.sh '{file_name}'",
shell=True,
)
else:
@ -150,6 +163,28 @@ def add_configuration(dct_xml, file_name, config):
not bool(lst_component),
f"Missing 'project/component' into {file_name}",
)
# Add python configuration
dct_component_py_conf = [
a
for a in lst_component
if a.get("@name") == "PyConsoleOptionsProvider"
]
if dct_component_py_conf:
# TODO check and force value
pass
else:
lst_component.append(
{
"@name": "PyConsoleOptionsProvider",
"option": {
"@name": "myShowDebugConsoleByDefault",
"@value": "false",
},
}
)
has_change = True
# Add configuration
dct_component = [
a for a in lst_component if a.get("@name") == "RunManager"
]
@ -157,12 +192,12 @@ def add_configuration(dct_xml, file_name, config):
# Create it
dct_component = {
"@name": "RunManager",
"@selected": "Python.pycharm_configuration",
"recent_temporary": {
"list": {
"item": {"@itemvalue": "Python.pycharm_configuration"}
}
},
# "@selected": "Python.pycharm_configuration",
# "recent_temporary": {
# "list": {
# "item": {"@itemvalue": "Python.pycharm_configuration"}
# }
# },
"configuration": [],
"list": {"item": []},
}
@ -219,116 +254,124 @@ def add_configuration(dct_xml, file_name, config):
for conf in lst_configuration:
print(f"\t{conf}")
if config.init:
if os.path.isfile(PATH_DEFAULT_CONFIGURATION):
with open(PATH_DEFAULT_CONFIGURATION) as txt:
for default_conf in csv.DictReader(txt):
conf_name = default_conf.get("name")
conf_folder = default_conf.get("folder")
conf_script_path = default_conf.get("script_path")
conf_script_path_replace = (
conf_script_path
if not conf_script_path.startswith("./")
else f"$PROJECT_DIR${conf_script_path[1:]}"
last_default = None
if not config.init:
return has_change
if not os.path.isfile(PATH_DEFAULT_CONFIGURATION):
_logger.error(f"Cannot read file '{PATH_DEFAULT_CONFIGURATION}'")
return has_change
with open(PATH_DEFAULT_CONFIGURATION) as txt:
for default_conf in csv.DictReader(txt):
conf_name = default_conf.get("name")
conf_folder = default_conf.get("folder")
conf_script_path = default_conf.get("script_path")
conf_default = bool(default_conf.get("default"))
if conf_default:
last_default = f"Python.{conf_name}"
conf_script_path_replace = (
conf_script_path
if not conf_script_path.startswith("./")
else f"$PROJECT_DIR${conf_script_path[1:]}"
)
conf_parameter = default_conf.get("parameters")
s_unique_key = (
f"d {conf_folder} s {conf_script_path} p {conf_parameter}"
)
if (
config.overwrite
or s_unique_key not in lst_unique_configuration
):
# add it!
if not config.overwrite and conf_name in lst_configuration:
_logger.error(
f"Cannot add configuration name '{conf_name}',"
" already exist. Delete it manually."
)
conf_parameter = default_conf.get("parameters")
s_unique_key = (
f"d {conf_folder} s"
f" {conf_script_path} p"
f" {conf_parameter}"
else:
has_change = True
lst_xml_configuration_name.append(
{"@itemvalue": f"Python.{conf_name}"}
)
if s_unique_key not in lst_unique_configuration:
# add it!
if conf_name in lst_configuration:
_logger.error(
f"Cannot add configuration name '{conf_name}',"
" already exist. Delete it manually."
)
else:
has_change = True
lst_xml_configuration_name.append(
{"@itemvalue": f"Python.conf_name"}
)
conf_full = {
"@name": conf_name,
"@type": "PythonConfigurationType",
"@factoryName": "Python",
"module": {"@name": PROJECT_NAME},
"option": [
{
"@name": "INTERPRETER_OPTIONS",
"@value": "",
},
{"@name": "PARENT_ENVS", "@value": "true"},
{
"@name": "SDK_HOME",
"@value": (
"$PROJECT_DIR$/.venv/bin/python"
),
},
{
"@name": "WORKING_DIRECTORY",
"@value": "$PROJECT_DIR$",
},
{
"@name": "IS_MODULE_SDK",
"@value": "false",
},
{
"@name": "ADD_CONTENT_ROOTS",
"@value": "true",
},
{
"@name": "ADD_SOURCE_ROOTS",
"@value": "true",
},
{
"@name": "SCRIPT_NAME",
"@value": conf_script_path_replace,
},
{
"@name": "PARAMETERS",
"@value": conf_parameter,
},
{
"@name": "SHOW_COMMAND_LINE",
"@value": "false",
},
{
"@name": "EMULATE_TERMINAL",
"@value": "false",
},
{
"@name": "MODULE_MODE",
"@value": "false",
},
{
"@name": "REDIRECT_INPUT",
"@value": "false",
},
{"@name": "INPUT_FILE", "@value": ""},
],
"envs": {
"env": {
"@name": "PYTHONUNBUFFERED",
"@value": "1",
}
},
"EXTENSION": {
"@ID": "PythonCoverageRunConfigurationExtension",
"@runner": "coverage.py",
},
"method": {"@v": "2"},
conf_full = {
"@name": conf_name,
"@type": "PythonConfigurationType",
"@factoryName": "Python",
"module": {"@name": PROJECT_NAME},
"option": [
{
"@name": "INTERPRETER_OPTIONS",
"@value": "",
},
{"@name": "PARENT_ENVS", "@value": "true"},
{
"@name": "SDK_HOME",
"@value": "$PROJECT_DIR$/.venv/bin/python",
},
{
"@name": "WORKING_DIRECTORY",
"@value": "$PROJECT_DIR$",
},
{
"@name": "IS_MODULE_SDK",
"@value": "false",
},
{
"@name": "ADD_CONTENT_ROOTS",
"@value": "true",
},
{
"@name": "ADD_SOURCE_ROOTS",
"@value": "true",
},
{
"@name": "SCRIPT_NAME",
"@value": conf_script_path_replace,
},
{
"@name": "PARAMETERS",
"@value": conf_parameter,
},
{
"@name": "SHOW_COMMAND_LINE",
"@value": "false",
},
{
"@name": "EMULATE_TERMINAL",
"@value": "false",
},
{
"@name": "MODULE_MODE",
"@value": "false",
},
{
"@name": "REDIRECT_INPUT",
"@value": "false",
},
{"@name": "INPUT_FILE", "@value": ""},
],
"envs": {
"env": {
"@name": "PYTHONUNBUFFERED",
"@value": "1",
}
if conf_folder:
conf_full["@folderName"] = conf_folder
lst_configuration_full.insert(0, conf_full)
else:
_logger.info(
f"Configuration already exist: '{s_unique_key}'"
)
else:
_logger.error(f"Cannot read file '{PATH_DEFAULT_CONFIGURATION}'")
},
"EXTENSION": {
"@ID": "PythonCoverageRunConfigurationExtension",
"@runner": "coverage.py",
},
"method": {"@v": "2"},
}
if conf_folder:
conf_full["@folderName"] = conf_folder
lst_configuration_full.insert(0, conf_full)
else:
_logger.info(f"Configuration already exist: '{s_unique_key}'")
if last_default:
dct_component["@selected"] = last_default
dct_component["recent_temporary"] = {
"list": {"item": {"@itemvalue": last_default}}
}
return has_change

View file

@ -35,8 +35,7 @@ echo "\n---- Installing nodeJS NPM and rtlcss for LTR support ----"
brew install nodejs npm openssl
sudo npm install -g rtlcss
sudo npm install -g less
sudo npm install -g prettier
sudo npm install -g prettier @prettier/plugin-xml
npm install
echo 'export PATH="/usr/local/opt/openssl@1.1/bin:$PATH"' >> ~/.zshrc

View file

@ -89,74 +89,46 @@ if [[ $retVal -ne 0 ]]; then
fi
echo -e "\n---- Installing nodeJS NPM and rtlcss for LTR support ----"
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
if [ "18.04" == "${UBUNTU_VERSION}" ]; then
sudo apt remove nodeJS npm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash
chmod +x ~/.nvm/nvm.sh
. $NVM_DIR/nvm.sh && nvm install 16.15.1
retVal=$?
if [[ $retVal -ne 0 ]]; then
echo "nvm installation error."
exit 1
fi
source ~/.bashrc
npm install npm@latest -g
retVal=$?
if [[ $retVal -ne 0 ]]; then
echo "npm install npm lastest installation error."
exit 1
fi
npm install -g rtlcss
retVal=$?
if [[ $retVal -ne 0 ]]; then
echo "npm install rtlcss installation error."
exit 1
fi
npm install -g less
retVal=$?
if [[ $retVal -ne 0 ]]; then
echo "npm install less installation error."
exit 1
fi
NODE_MAJOR=16
else
curl -fsSL https://deb.nodesource.com/setup_current.x | sudo -E bash -
sudo apt-get install -y nodejs
retVal=$?
if [[ $retVal -ne 0 ]]; then
echo "apt-get nodejs installation error."
exit 1
fi
sudo npm install npm@latest -g
retVal=$?
if [[ $retVal -ne 0 ]]; then
echo "npm install npm lastest installation error."
exit 1
fi
sudo npm install -g rtlcss
retVal=$?
if [[ $retVal -ne 0 ]]; then
echo "npm install rtlcss installation error."
exit 1
fi
sudo npm install -g less
retVal=$?
if [[ $retVal -ne 0 ]]; then
echo "npm install less installation error."
exit 1
fi
NODE_MAJOR=20
fi
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list
sudo apt-get update
sudo apt-get install nodejs -y
sudo npm install npm@latest -g
retVal=$?
if [[ $retVal -ne 0 ]]; then
echo "npm install npm lastest installation error."
exit 1
fi
sudo npm install -g rtlcss
retVal=$?
if [[ $retVal -ne 0 ]]; then
echo "npm install rtlcss installation error."
exit 1
fi
sudo npm install -g less
retVal=$?
if [[ $retVal -ne 0 ]]; then
echo "npm install less installation error."
exit 1
fi
echo -e "\n---- Test tool ----"
sudo npm install -g prettier
npm install
retVal=$?
if [[ $retVal -ne 0 ]]; then
echo "npm install prettier installation error."
exit 1
fi
sudo npm install -g prettier @prettier/plugin-xml
retVal=$?
if [[ $retVal -ne 0 ]]; then
echo "npm install prettier plugin-xml installation error."
echo "npm install prettier + plugin-xml installation error."
exit 1
fi

View file

@ -75,6 +75,7 @@ if [[ ! -d ${VENV_PATH} ]]; then
exit 1
fi
fi
source ./.venv/bin/activate
#if [[ ! -d "${POETRY_PATH}" ]]; then
# # Delete directory ~/.poetry and .venv to force update to new version

View file

@ -17,6 +17,8 @@ if [[ $retVal -ne 0 ]]; then
exit 1
fi
npm install
## Install maintainer-tools
#cd script/OCA_maintainer-tools || exit
## virtualenv is not installed by default

View file

@ -2,7 +2,7 @@
# This will format all python file
# argument 1: directory or file to format
source ./.venv/bin/activate
black -l 79 --preview -t py37 $@
black -l 79 --preview -t py37 "$@"
retVal=$?
if [[ $retVal -ne 0 ]]; then
echo "Error black format"

8
script/maintenance/format.sh Executable file
View file

@ -0,0 +1,8 @@
#!/usr/bin/env bash
cmd1="./script/maintenance/format_python.sh \"$*\""
cmd2="find \"$*\" -type f -not -path \"*/not_supported_files/*\" -name '*.xml' -print0 | parallel -0 ./script/maintenance/prettier_xml.sh {}"
cmd3="find \"$*\" -type f -not -path \"*/not_supported_files/*\" -name '*.js' -print0 | parallel -0 ./script/maintenance/prettier.sh {}"
cmd4="find \"$*\" -type f -not -path \"*/not_supported_files/*\" -name '*.css' -print0 | parallel -0 ./script/maintenance/prettier.sh {}"
cmd5="find \"$*\" -type f -not -path \"*/not_supported_files/*\" -name '*.scss' -print0 | parallel -0 ./script/maintenance/prettier.sh {}"
cmd6="find \"$*\" -type f -not -path \"*/not_supported_files/*\" -name '*.html' -print0 | parallel -0 ./script/maintenance/prettier.sh {}"
parallel ::: "$cmd1" "$cmd2" "$cmd3" "$cmd4" "$cmd5" "$cmd6"

View file

@ -1,3 +1,5 @@
#!/usr/bin/env bash
.venv/bin/isort --profile black -l 79 "$@"
source ./.venv/bin/activate
isort --profile black -l 79 "$@"
#./.venv/bin/isort --profile black -l 79 "$@"
./script/maintenance/black.sh "$@"

View file

@ -1,7 +1,7 @@
#!/usr/bin/env bash
# This will format all js,css,html
# argument 1: directory or file to format
prettier --write $@
./node_modules/.bin/prettier --tab-width 4 --print-width 120 --no-bracket-spacing --write "$@"
retVal=$?
if [[ $retVal -ne 0 ]]; then
echo "Error prettier format"

View file

@ -4,14 +4,14 @@
STR_ARG="'$*'"
if [[ "${STR_ARG}" = *"/data/"* ]]; then
# Need to keep width with data, else add corrupted string data
prettier --xml-whitespace-sensitivity "ignore" --prose-wrap always --tab-width 4 --no-bracket-spacing --print-width 999999999 --write $@
./node_modules/.bin/prettier --plugin=@prettier/plugin-xml --xml-whitespace-sensitivity "ignore" --prose-wrap always --tab-width 4 --no-bracket-spacing --print-width 999999999 --write "$@"
else
prettier --xml-whitespace-sensitivity "ignore" --prose-wrap always --tab-width 4 --no-bracket-spacing --print-width 120 --write $@
./node_modules/.bin/prettier --plugin=@prettier/plugin-xml --xml-whitespace-sensitivity "ignore" --prose-wrap always --tab-width 4 --no-bracket-spacing --print-width 120 --write "$@"
# strict xml-whitespace-sensitivity will keep space alignement
#prettier --xml-whitespace-sensitivity "strict" --prose-wrap always --tab-width 4 --no-bracket-spacing --print-width 120 --write $@
fi
retVal=$?
if [[ $retVal -ne 0 ]]; then
echo "Error prettier format"
echo "Error prettier-xml format"
exit 1
fi

View file

@ -8,7 +8,7 @@
git daemon --base-path=. --export-all --reuseaddr --informative-errors --verbose &
DAEMON_PID=$!
./.venv/repo init -u git://127.0.0.1:9418/ -b $(git rev-parse --verify HEAD) -m ${EL_MANIFEST_DEV}
./.venv/repo init -u git://127.0.0.1:9418/ -b $(git rev-parse --verify HEAD) -m ${EL_MANIFEST_DEV} "$@"
./.venv/repo sync -v --force-sync -m ${EL_MANIFEST_DEV}
kill ${DAEMON_PID}

View file

@ -1,26 +1,47 @@
#!/usr/bin/env bash
# Open a new gnome-terminal with different path on new tab
working_path=`readlink -f .`
working_path=$(readlink -f .)
paths=(
"${working_path}/"
"${working_path}/addons/TechnoLibre_odoo-code-generator"
"${working_path}/addons/TechnoLibre_odoo-code-generator-template"
"${working_path}/addons/ERPLibre_erplibre_addons"
"${working_path}/addons/OCA_server-tools"
"${working_path}/"
# "${working_path}/addons/TechnoLibre_odoo-code-generator"
# "${working_path}/addons/TechnoLibre_odoo-code-generator-template"
"${working_path}/addons/ERPLibre_erplibre_addons"
# "${working_path}/addons/OCA_server-tools"
)
cmd_before="cd "
# when change directory, open a new tab with command to execute
cmd_after=";gnome-terminal --tab -- bash -c 'git status;bash';"
#cmd_after=";gnome-terminal --tab;"
LONGCMD=""
for t in "${paths[@]}"; do
LONGCMD+=${cmd_before}${t}${cmd_after}
done
first_iteration=true
if [[ "${OSTYPE}" == "linux-gnu" ]]; then
cmd_before="cd "
cmd_after_first=";gnome-terminal --tab -- bash -c 'source ./.venv/bin/activate;git status;bash';"
cmd_after=";gnome-terminal --tab -- bash -c 'git status;bash';"
LONGCMD=""
for t in "${paths[@]}"; do
if $first_iteration; then
LONGCMD+="${cmd_before}${t}${cmd_after_first}"
first_iteration=false
else
LONGCMD+="${cmd_before}${t}${cmd_after}"
fi
done
gnome-terminal --window -- bash -c "${LONGCMD}"
elif [[ "${OSTYPE}" == "darwin"* ]]; then
paths=("${paths[@]:1}")
#echo $LONGCMD
# Initialisation de la commande osascript
osascript_command="osascript -e 'tell application \"Terminal\"'"
# Open all terminal from paths list
#echo "gnome-terminal --window -- bash -c \"${LONGCMD}\""
gnome-terminal --window -- bash -c "${LONGCMD}"
# Boucle pour ajouter des commandes pour ouvrir de nouveaux onglets et exécuter les scripts batch
for t in "${paths[@]}"; do
if $first_iteration; then
osascript_command+=" -e 'tell application \"System Events\" to keystroke \"t\" using {command down}' -e 'delay 0.1' -e 'do script \"cd ${t}; source ./.venv/bin/activate; git status\" in front window'"
first_iteration=false
else
osascript_command+=" -e 'tell application \"System Events\" to keystroke \"t\" using {command down}' -e 'delay 0.1' -e 'do script \"cd ${t}; git status\" in front window'"
fi
done
osascript_command+=" -e 'end tell'"
# Exécution de la commande osascript
eval "$osascript_command"
fi

View file

Binary file not shown.

View file

@ -0,0 +1,5 @@
sudo apt install libcairo2-dev python3-dev pkg-config libxt-dev libgirepository1.0-dev
pip install pycairo PyGObject
https://github.com/szemate/pyselenium-video-recorder

Binary file not shown.

View file

@ -0,0 +1,113 @@
"""Video recorder for Selenium WebDriver."""
import threading
import gi
gi.require_version("Gst", "1.0")
from gi.repository import Gst
Gst.init(None)
class VideoRecorder(object):
"""Record video of a Selenium test run in WebM format through repeated
screenshot captures.
:type driver: selenium.webdriver.Remote
:param filename: Path of the video file to create, or `None` to view live
video output.
:param framerate: Rate of screenshot capture as fraction [fps].
:param width: Crop screenshots to this width [pixels].
:param height: Crop screenshots to this height [pixels].
"""
def __init__( # pylint: disable=too-many-arguments
self,
driver,
filename="video.webm",
framerate="25/1",
width=None,
height=None,
):
self.driver = driver
_patch_driver(self.driver)
if filename and not filename.endswith(".webm"):
filename += ".webm"
caps = ["video/x-raw", "framerate={}".format(framerate)]
if width:
caps.append("width={}".format(width))
if height:
caps.append("height={}".format(height))
elements = [
"appsrc name=src is-live=true do-timestamp=true caps=image/png",
"pngdec",
"videoconvert",
"videorate",
"videocrop name=crop",
",".join(caps),
"queue",
]
if filename:
elements += [
"vp8enc",
"webmmux",
"filesink location={}".format(filename),
]
else:
elements.append("autovideosink sync=false")
self._pipeline = Gst.parse_launch(" ! ".join(elements))
self._appsrc = self._pipeline.get_by_name("src")
self._appsrc.connect("need-data", self._push_screenshot)
videocrop = self._pipeline.get_by_name("crop")
if width:
videocrop.set_property("right", -1) # Auto-crop
if height:
videocrop.set_property("bottom", -1) # Auto-crop
def start(self):
"""Start video recording."""
self._pipeline.set_state(Gst.State.PLAYING)
def stop(self):
"""Stop video recording."""
self._appsrc.emit("end-of-stream")
self._pipeline.set_state(Gst.State.NULL)
def _push_screenshot(self, *_):
"""Emit a WebDriver screenshot from appsrc."""
self._appsrc.emit(
"push-buffer",
Gst.Buffer.new_wrapped(self.driver.get_screenshot_as_png()),
)
def VideoViewer(*args, **kwargs):
"""Shorthand for `VideoRecorder(filename=None)`.
Useful with PhantomJS.
"""
kwargs["filename"] = None
return VideoRecorder(*args, **kwargs)
def _patch_driver(driver):
"""Prevent failures caused by concurrent connections to the remote
WebDriver.
Another option would be to use a WebDriver proxy. Monkey patching `driver`
is simpler, though more hacky.
"""
lock = threading.Lock()
execute_unsafe = driver.execute
def execute_safe(driver_command, params=None):
with lock:
return execute_unsafe(driver_command, params)
driver.execute = execute_safe

44
script/selenium/web_login.py Executable file
View file

@ -0,0 +1,44 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.by import By
# Configuration pour lancer Firefox en mode de navigation privée
firefox_options = webdriver.FirefoxOptions()
firefox_options.add_argument("--private")
# Définissez la préférence pour les notifications de bureau
# 1 signifie "autoriser", 2 signifie "bloquer"
firefox_options.set_preference("permissions.default.desktop-notification", 1)
# Créez une instance du navigateur Firefox avec les options de navigation privée
driver = webdriver.Firefox(options=firefox_options)
# Ouvrez la page web
driver.get("http://127.0.0.1:8069/web")
# Trouvez les éléments du formulaire
courriel_input = driver.find_element(By.NAME, "login")
mot_de_passe_input = driver.find_element(By.NAME, "password")
try:
connexion_button = driver.find_element(
By.XPATH,
"/html/body/div/div/div/form/div[3]/button"
# '//button[contains(text(), "Log in")]'
)
except Exception:
connexion_button = driver.find_element(
By.XPATH,
"/html/body/div/main/div/form/div[3]/button"
# '//button[contains(text(), "Connexion")]'
)
# Remplissez le courriel et le mot de passe
courriel_input.send_keys("admin")
mot_de_passe_input.send_keys("admin")
# Cliquez sur le bouton "Connexion"
connexion_button.click()
# Fermez le navigateur
# driver.quit()

View file

@ -0,0 +1,169 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import sys
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
private_mode = True
record_mode = False
dark_reader_mode = True
def click(driver, xpath, time=5):
wait = WebDriverWait(driver, time)
button = wait.until(
EC.element_to_be_clickable(
(
By.XPATH,
xpath,
)
)
)
button.click()
if record_mode:
new_path = os.path.normpath(
os.path.join(os.path.dirname(__file__), "..", "..")
)
sys.path.append(new_path)
from script.selenium.selenium_video import VideoRecorder
# Configuration pour lancer Firefox en mode de navigation privée
firefox_options = webdriver.FirefoxOptions()
if private_mode:
firefox_options.add_argument("--private")
# Définissez la préférence pour les notifications de bureau
# 1 signifie "autoriser", 2 signifie "bloquer"
firefox_options.set_preference("permissions.default.desktop-notification", 1)
# Créez une instance du navigateur Firefox avec les options de navigation privée
driver = webdriver.Firefox(options=firefox_options)
# Ajout de l'enregistrement
if record_mode:
video_recorder = VideoRecorder(driver)
else:
video_recorder = None
# Install DarkReader to help my eyes
# TODO do a script to check if it's the last version
if dark_reader_mode:
driver.install_addon(
"./script/selenium/darkreader-firefox.xpi", temporary=True
)
driver.install_addon(
"./script/selenium/odoo_debug-4.0.xpi", temporary=True
)
if private_mode and dark_reader_mode:
driver.get("about:addons")
# Enable Dark Reader into incognito
click(driver, "/html/body/div/div[1]/categories-box/button[2]")
click(
driver,
"/html/body/div/div[2]/div/addon-list/section[1]/addon-card/div/div/div/div/button",
)
click(
driver,
"/html/body/div/div[2]/div/addon-list/section[1]/addon-card/div/addon-options/panel-list/panel-item[5]",
)
click(
driver,
"/html/body/div/div[2]/div/addon-card/div/addon-details/named-deck/section/div[5]/div/label[1]/input",
)
# Enable Odoo_debug into incognito
# Back
click(driver, "/html/body/div/div[2]/addon-page-header/div/div[2]/button")
click(
driver,
"/html/body/div/div[2]/div/addon-list/section[1]/addon-card[2]/div/div/div/div/button",
)
click(
driver,
"/html/body/div/div[2]/div/addon-list/section[1]/addon-card[2]/div/addon-options/panel-list/panel-item[5]",
)
click(
driver,
"/html/body/div/div[2]/div/addon-card/div/addon-details/named-deck/section/div[5]/div/label[1]/input",
)
# Ouvrez la page web
driver.get("http://127.0.0.1:8069/web")
# Close tab opening by DarkReader
if not private_mode and dark_reader_mode:
driver.switch_to.window(driver.window_handles[-1])
driver.close()
driver.switch_to.window(driver.window_handles[0])
# Démarrer l'enregistrement
if record_mode:
video_recorder.start()
# Trouvez les éléments du formulaire
courriel_input = driver.find_element(By.NAME, "login")
mot_de_passe_input = driver.find_element(By.NAME, "password")
try:
connexion_button = driver.find_element(
By.XPATH,
"/html/body/div/div/div/form/div[3]/button"
# '//button[contains(text(), "Log in")]'
)
except Exception:
connexion_button = driver.find_element(
By.XPATH,
"/html/body/div/main/div/form/div[3]/button"
# '//button[contains(text(), "Connexion")]'
)
# Remplissez le courriel et le mot de passe
courriel_input.send_keys("admin")
mot_de_passe_input.send_keys("admin")
# Cliquez sur le bouton "Connexion"
connexion_button.click()
# Attendez que l'élément soit cliquable
wait = WebDriverWait(driver, 5)
# menu_toggle = wait.until(
# EC.element_to_be_clickable((By.XPATH, "/html/body/header/nav/ul[1]/li/a"))
# )
#
# # Cliquez sur l'élément
# menu_toggle.click()
#
# # Attendez que le lien soit cliquable
# menu_item = wait.until(
# EC.element_to_be_clickable(
# (
# By.XPATH,
# "/html/body/header/nav/ul[1]/li/div/a[2]",
# )
# )
# )
# Open View
click(driver, "/html/body/header/nav/div/div[1]/div[2]/div/div/div/ul/li[2]/a")
click(driver, "/html/body/div[1]/main/div[2]/div/div/table/tbody/tr[1]/td[2]")
# Arrêter l'enregistrement
if record_mode:
video_recorder.stop()
# Open conversation chat
# conversation_button = driver.find_element(By.XPATH, '/html/body/header/nav/ul[3]/li[2]/a')
# conversation_button.click()
# Close bot chat
# conversation_button = driver.find_element(By.XPATH, '/html/body/div[3]/div[1]/span[2]/a[2]')
# conversation_button.click()
# Fermez le navigateur
# driver.quit()

View file

@ -0,0 +1,171 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import sys
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
private_mode = True
record_mode = False
dark_reader_mode = True
def click(driver, xpath, time=5):
wait = WebDriverWait(driver, time)
button = wait.until(
EC.element_to_be_clickable(
(
By.XPATH,
xpath,
)
)
)
button.click()
if record_mode:
new_path = os.path.normpath(
os.path.join(os.path.dirname(__file__), "..", "..")
)
sys.path.append(new_path)
from script.selenium.selenium_video import VideoRecorder
# Configuration pour lancer Firefox en mode de navigation privée
firefox_options = webdriver.FirefoxOptions()
if private_mode:
firefox_options.add_argument("--private")
# Définissez la préférence pour les notifications de bureau
# 1 signifie "autoriser", 2 signifie "bloquer"
firefox_options.set_preference("permissions.default.desktop-notification", 1)
# Créez une instance du navigateur Firefox avec les options de navigation privée
driver = webdriver.Firefox(options=firefox_options)
# Ajout de l'enregistrement
if record_mode:
video_recorder = VideoRecorder(driver)
else:
video_recorder = None
# Install DarkReader to help my eyes
# TODO do a script to check if it's the last version
if dark_reader_mode:
driver.install_addon(
"./script/selenium/darkreader-firefox.xpi", temporary=True
)
driver.install_addon(
"./script/selenium/odoo_debug-4.0.xpi", temporary=True
)
if private_mode and dark_reader_mode:
driver.get("about:addons")
click(driver, "/html/body/div/div[1]/categories-box/button[2]")
click(
driver,
"/html/body/div/div[2]/div/addon-list/section[1]/addon-card/div/div/div/div/button",
)
click(
driver,
"/html/body/div/div[2]/div/addon-list/section[1]/addon-card/div/addon-options/panel-list/panel-item[5]",
)
click(
driver,
"/html/body/div/div[2]/div/addon-card/div/addon-details/named-deck/section/div[5]/div/label[1]/input",
)
# Enable Odoo_debug into incognito
# Back
click(driver, "/html/body/div/div[2]/addon-page-header/div/div[2]/button")
click(
driver,
"/html/body/div/div[2]/div/addon-list/section[1]/addon-card[2]/div/div/div/div/button",
)
click(
driver,
"/html/body/div/div[2]/div/addon-list/section[1]/addon-card[2]/div/addon-options/panel-list/panel-item[5]",
)
click(
driver,
"/html/body/div/div[2]/div/addon-card/div/addon-details/named-deck/section/div[5]/div/label[1]/input",
)
# Ouvrez la page web
driver.get("http://127.0.0.1:8069/web")
# Close tab opening by DarkReader
if not private_mode and dark_reader_mode:
driver.switch_to.window(driver.window_handles[-1])
driver.close()
driver.switch_to.window(driver.window_handles[0])
# Démarrer l'enregistrement
if record_mode:
video_recorder.start()
# Trouvez les éléments du formulaire
courriel_input = driver.find_element(By.NAME, "login")
mot_de_passe_input = driver.find_element(By.NAME, "password")
try:
connexion_button = driver.find_element(
By.XPATH,
"/html/body/div/div/div/form/div[3]/button"
# '//button[contains(text(), "Log in")]'
)
except Exception:
connexion_button = driver.find_element(
By.XPATH,
"/html/body/div/main/div/form/div[3]/button"
# '//button[contains(text(), "Connexion")]'
)
# Remplissez le courriel et le mot de passe
courriel_input.send_keys("admin")
mot_de_passe_input.send_keys("admin")
# Cliquez sur le bouton "Connexion"
connexion_button.click()
# Open View
click(driver, "/html/body/header/nav/div/div[1]/div[2]/div/div/div/ul/li[2]/a")
click(driver, "/html/body/div[1]/main/div[2]/div/div/table/tbody/tr[1]/td[2]")
click(driver, "/html/body/header/nav/div/div[1]/div[2]/div/div/div/ul/li[2]/a")
click(driver, "/html/body/div[1]/main/div[2]/div/div/table/tbody/tr[1]/td[2]")
# CG self
# Bouton modifier
click(driver, "/html/body/div[1]/main/div[1]/div[2]/div/div/div[1]/button[1]")
# Tab CG
click(driver, "/html/body/div[1]/main/div[2]/div/div/div[7]/ul/li[3]/a")
# Disable «Stop Execution if Env Not Clean
# click(
# driver,
# "/html/body/div[1]/main/div[2]/div/div/div[7]/div/div[3]/div[2]/table[2]/tbody/tr/td[1]/label",
# )
# Gen
click(
driver,
"/html/body/div[1]/main/div[2]/div/div/div[7]/div/div[3]/div[2]/table[1]/tbody/tr[2]/td[1]/button",
)
# Check error
click(driver, "/html/body/div[1]/main/div[2]/div/div/div[7]/ul/li[14]/a")
# click(driver, "/html/body/div[1]/main/div[2]/div/div/div[6]/div/div[14]/div/div[2]/table/tbody/tr[1]", time=60*2)
# Arrêter l'enregistrement
if record_mode:
video_recorder.stop()
# Open conversation chat
# conversation_button = driver.find_element(By.XPATH, '/html/body/header/nav/ul[3]/li[2]/a')
# conversation_button.click()
# Close bot chat
# conversation_button = driver.find_element(By.XPATH, '/html/body/div[3]/div[1]/span[2]/a[2]')
# conversation_button.click()
# Fermez le navigateur
# driver.quit()

View file

@ -0,0 +1,171 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import sys
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
private_mode = True
record_mode = False
dark_reader_mode = True
def click(driver, xpath, time=5):
wait = WebDriverWait(driver, time)
button = wait.until(
EC.element_to_be_clickable(
(
By.XPATH,
xpath,
)
)
)
button.click()
if record_mode:
new_path = os.path.normpath(
os.path.join(os.path.dirname(__file__), "..", "..")
)
sys.path.append(new_path)
from script.selenium.selenium_video import VideoRecorder
# Configuration pour lancer Firefox en mode de navigation privée
firefox_options = webdriver.FirefoxOptions()
if private_mode:
firefox_options.add_argument("--private")
# Définissez la préférence pour les notifications de bureau
# 1 signifie "autoriser", 2 signifie "bloquer"
firefox_options.set_preference("permissions.default.desktop-notification", 1)
# Créez une instance du navigateur Firefox avec les options de navigation privée
driver = webdriver.Firefox(options=firefox_options)
# Ajout de l'enregistrement
if record_mode:
video_recorder = VideoRecorder(driver)
else:
video_recorder = None
# Install DarkReader to help my eyes
# TODO do a script to check if it's the last version
if dark_reader_mode:
driver.install_addon(
"./script/selenium/darkreader-firefox.xpi", temporary=True
)
driver.install_addon(
"./script/selenium/odoo_debug-4.0.xpi", temporary=True
)
if private_mode and dark_reader_mode:
driver.get("about:addons")
click(driver, "/html/body/div/div[1]/categories-box/button[2]")
click(
driver,
"/html/body/div/div[2]/div/addon-list/section[1]/addon-card/div/div/div/div/button",
)
click(
driver,
"/html/body/div/div[2]/div/addon-list/section[1]/addon-card/div/addon-options/panel-list/panel-item[5]",
)
click(
driver,
"/html/body/div/div[2]/div/addon-card/div/addon-details/named-deck/section/div[5]/div/label[1]/input",
)
# Enable Odoo_debug into incognito
# Back
click(driver, "/html/body/div/div[2]/addon-page-header/div/div[2]/button")
click(
driver,
"/html/body/div/div[2]/div/addon-list/section[1]/addon-card[2]/div/div/div/div/button",
)
click(
driver,
"/html/body/div/div[2]/div/addon-list/section[1]/addon-card[2]/div/addon-options/panel-list/panel-item[5]",
)
click(
driver,
"/html/body/div/div[2]/div/addon-card/div/addon-details/named-deck/section/div[5]/div/label[1]/input",
)
# Ouvrez la page web
driver.get("http://127.0.0.1:8069/web")
# Close tab opening by DarkReader
if not private_mode and dark_reader_mode:
driver.switch_to.window(driver.window_handles[-1])
driver.close()
driver.switch_to.window(driver.window_handles[0])
# Démarrer l'enregistrement
if record_mode:
video_recorder.start()
# Trouvez les éléments du formulaire
courriel_input = driver.find_element(By.NAME, "login")
mot_de_passe_input = driver.find_element(By.NAME, "password")
try:
connexion_button = driver.find_element(
By.XPATH,
"/html/body/div/div/div/form/div[3]/button"
# '//button[contains(text(), "Log in")]'
)
except Exception:
connexion_button = driver.find_element(
By.XPATH,
"/html/body/div/main/div/form/div[3]/button"
# '//button[contains(text(), "Connexion")]'
)
# Remplissez le courriel et le mot de passe
courriel_input.send_keys("admin")
mot_de_passe_input.send_keys("admin")
# Cliquez sur le bouton "Connexion"
connexion_button.click()
# Open View
click(driver, "/html/body/header/nav/div/div[1]/div[2]/div/div/div/ul/li[2]/a")
click(driver, "/html/body/div[1]/main/div[2]/div/div/table/tbody/tr[1]/td[2]")
click(driver, "/html/body/header/nav/div/div[1]/div[2]/div/div/div/ul/li[2]/a")
click(driver, "/html/body/div[1]/main/div[2]/div/div/table/tbody/tr[1]/td[2]")
# CG self
# Bouton modifier
click(driver, "/html/body/div[1]/main/div[1]/div[2]/div/div/div[1]/button[1]")
# Tab CG
click(driver, "/html/body/div[1]/main/div[2]/div/div/div[7]/ul/li[3]/a")
# Disable «Stop Execution if Env Not Clean
click(
driver,
"/html/body/div[1]/main/div[2]/div/div/div[7]/div/div[3]/div[2]/table[2]/tbody/tr/td[1]/label",
)
# Gen
click(
driver,
"/html/body/div[1]/main/div[2]/div/div/div[7]/div/div[3]/div[2]/table[1]/tbody/tr[2]/td[1]/button",
)
# Check error
click(driver, "/html/body/div[1]/main/div[2]/div/div/div[7]/ul/li[14]/a")
# click(driver, "/html/body/div[1]/main/div[2]/div/div/div[6]/div/div[14]/div/div[2]/table/tbody/tr[1]", time=60*2)
# Arrêter l'enregistrement
if record_mode:
video_recorder.stop()
# Open conversation chat
# conversation_button = driver.find_element(By.XPATH, '/html/body/header/nav/ul[3]/li[2]/a')
# conversation_button.click()
# Close bot chat
# conversation_button = driver.find_element(By.XPATH, '/html/body/div[3]/div[1]/span[2]/a[2]')
# conversation_button.click()
# Fermez le navigateur
# driver.quit()

View file

@ -496,9 +496,9 @@ async def test_exec(
hook.write(new_hook_line)
# Format editing code before commit
await lib_asyncio.run_command_get_output(
"./script/maintenance/black.sh", temp_dir_name
)
# await lib_asyncio.run_command_get_output(
# "./script/maintenance/format.sh", temp_dir_name
# )
# init repo with git
for dir_to_git in lst_path_to_add_config: