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:
commit
6c66f36be5
36 changed files with 1124 additions and 244 deletions
20
.editorconfig
Normal file
20
.editorconfig
Normal 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
2
.gitignore
vendored
|
|
@ -24,3 +24,5 @@ get-poetry.py
|
|||
artifacts
|
||||
wkhtmltox*
|
||||
cache
|
||||
|
||||
node_modules
|
||||
|
|
|
|||
17
CHANGELOG.md
17
CHANGELOG.md
|
|
@ -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**
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
||||
|
|
|
|||
|
|
|
@ -10,3 +10,4 @@ doc/odoo_documentation-user
|
|||
artifacts
|
||||
cache
|
||||
htmlcov
|
||||
node_modules
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
66
package-lock.json
generated
Normal 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
11
package.json
Normal 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"
|
||||
}
|
||||
}
|
||||
|
|
@ -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=$?
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
8
script/maintenance/format.sh
Executable 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"
|
||||
|
|
@ -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 "$@"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
0
script/selenium/__init__.py
Normal file
0
script/selenium/__init__.py
Normal file
BIN
script/selenium/darkreader-firefox.xpi
Normal file
BIN
script/selenium/darkreader-firefox.xpi
Normal file
Binary file not shown.
5
script/selenium/install.md
Normal file
5
script/selenium/install.md
Normal 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
|
||||
BIN
script/selenium/odoo_debug-4.0.xpi
Normal file
BIN
script/selenium/odoo_debug-4.0.xpi
Normal file
Binary file not shown.
113
script/selenium/selenium_video.py
Normal file
113
script/selenium/selenium_video.py
Normal 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
44
script/selenium/web_login.py
Executable 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()
|
||||
169
script/selenium/web_login_open_me_devops.py
Executable file
169
script/selenium/web_login_open_me_devops.py
Executable 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()
|
||||
171
script/selenium/web_login_open_me_devops_auto.py
Executable file
171
script/selenium/web_login_open_me_devops_auto.py
Executable 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()
|
||||
171
script/selenium/web_login_open_me_devops_auto_force.py
Executable file
171
script/selenium/web_login_open_me_devops_auto_force.py
Executable 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()
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Reference in a new issue