Merge branch 'develop_support_arch_linux'
- Upgrade odoo 14 and 16 - Improve selenium odoo navigation and recording - Improve installation ERPLibre and docker build
This commit is contained in:
commit
4f39f86cc5
30 changed files with 4204 additions and 2808 deletions
1
.erplibre-semver-version
Normal file
1
.erplibre-semver-version
Normal file
|
|
@ -0,0 +1 @@
|
|||
1.5.0
|
||||
20
Makefile
20
Makefile
|
|
@ -30,6 +30,18 @@ else
|
|||
endif
|
||||
endif
|
||||
|
||||
|
||||
# Example for update
|
||||
.PHONY: custom_run_example
|
||||
custom_run_example:
|
||||
./run.sh -d example_prod
|
||||
|
||||
.PHONY: custom_update_example
|
||||
custom_update_example:
|
||||
./script/database/db_restore.py --database example_prod --image image_name_to_restore
|
||||
./script/addons/update_addons_all.sh example_prod
|
||||
./script/addons/update_prod_to_dev.sh example_prod
|
||||
|
||||
#########
|
||||
# RUN #
|
||||
#########
|
||||
|
|
@ -727,6 +739,13 @@ tag_push_all:
|
|||
open_terminal:
|
||||
./script/open_terminal_code_generator.sh
|
||||
|
||||
##############
|
||||
# selenium #
|
||||
##############
|
||||
.PHONY: open_selenium
|
||||
open_selenium:
|
||||
./.venv/bin/python ./script/selenium/web_login.py
|
||||
|
||||
############
|
||||
# format #
|
||||
############
|
||||
|
|
@ -938,6 +957,7 @@ config_install:
|
|||
|
||||
.PHONY: config_update
|
||||
config_update:
|
||||
# Need http to configure the file config.conf, or will disable it
|
||||
./run.sh -c config.conf -s --stop-after-init
|
||||
|
||||
.PHONY: config_update_over_proxy
|
||||
|
|
|
|||
30
doc/FAQ.md
30
doc/FAQ.md
|
|
@ -122,6 +122,36 @@ git reset --hard REF_OF_REMOTES/m
|
|||
> git reset --hard remotes/origin/rel/8953/zd552kl/7.1.1-11.40.208
|
||||
```
|
||||
|
||||
### fatal: GitCommandError: git command failure
|
||||
|
||||
Example of error after an installation with git-repo:
|
||||
|
||||
```
|
||||
raise GitCommandError(
|
||||
git_command.GitCommandError: GitCommandError: git command failure
|
||||
Project: manifests
|
||||
Args: rev-list ^e96a83f03665ecc1b151331776909be32d5e2c7b HEAD --
|
||||
Stdout:
|
||||
None
|
||||
Stderr:
|
||||
fatal: bad revision 'HEAD'
|
||||
Skipped fetching project manifests (already have persistent ref)
|
||||
fatal: GitCommandError: git command failure
|
||||
Project: manifests
|
||||
Args: rev-list ^HEAD c8e64956f188f77abcfa7ff0e764af97162d3071 --
|
||||
Stdout:
|
||||
None
|
||||
Stderr:
|
||||
fatal: bad revision '^HEAD'
|
||||
```
|
||||
|
||||
Solution: Check files into directory `cd .repo/manifests` with commande `git status`. If
|
||||
you
|
||||
have some differences in stage, you can try `git reset --hard` and redo the
|
||||
installation.
|
||||
|
||||
If it's not working, re-clone the repo and do a fresh installation.
|
||||
|
||||
## OSX installation
|
||||
|
||||
### Docker installation
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ Execute migration with OpenUpgrade.
|
|||
|
||||
```bash
|
||||
make config_gen_migration
|
||||
./.venv/bin/python ./script/OCA_OpenUpgrade/odoo-bin -c ./config.conf --update all --stop-after-init -d BD
|
||||
./.venv/bin/python ./script/OCA_OpenUpgrade/odoo-bin -c ./config.conf --no-http --update all --stop-after-init -d BD
|
||||
```
|
||||
|
||||
## Migration Odoo 13 to Odoo 14
|
||||
|
|
@ -61,5 +61,5 @@ Replace BD to your database name.
|
|||
|
||||
```bash
|
||||
make config_gen_migration
|
||||
./run.sh --upgrade-path=./script/OCA_OpenUpgrade/openupgrade_scripts/scripts --update all --stop-after-init --load=base,web,openupgrade_framework -d BD
|
||||
./run.sh --upgrade-path=./script/OCA_OpenUpgrade/openupgrade_scripts/scripts --update all --no-http --stop-after-init --load=base,web,openupgrade_framework -d BD
|
||||
```
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ database. WARNING, this is not safe for production, you will expose all data.
|
|||
Update all features.
|
||||
|
||||
```bash
|
||||
./run.sh --limit-time-real 99999 --stop-after-init -u all -d DATABASE
|
||||
./run.sh --limit-time-real 99999 --no-http --stop-after-init -u all -d DATABASE
|
||||
```
|
||||
|
||||
# Postgresql
|
||||
|
|
|
|||
|
|
@ -49,17 +49,17 @@ Great idea to run it when updating Odoo, it updates each module database.
|
|||
First execution, install you requirements, choose a new database.
|
||||
|
||||
```bash
|
||||
./run.sh -d [DATABASE] -i [module to test] --test-enable --stop-after-init --log-level=test
|
||||
./run.sh -d [DATABASE] -i [module to test] --test-enable --no-http --stop-after-init --log-level=test
|
||||
```
|
||||
|
||||
Execute your test on a specific module.
|
||||
|
||||
```bash
|
||||
./run.sh -d [DATABASE] -u [module to test] --test-enable --stop-after-init --log-level=test
|
||||
./run.sh -d [DATABASE] -u [module to test] --test-enable --no-http --stop-after-init --log-level=test
|
||||
```
|
||||
|
||||
Execute your test on a specific module with tags.
|
||||
|
||||
```bash
|
||||
./run.sh -d [DATABASE] -u [module to test] --test-enable --stop-after-init --log-level=test --test-tags [module_name][tags]
|
||||
./run.sh -d [DATABASE] -u [module to test] --test-enable --no-http --stop-after-init --log-level=test --test-tags [module_name][tags]
|
||||
```
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ RUN cd $ODOO_PREFIX && \
|
|||
RUN cd $ODOO_PREFIX && \
|
||||
ls -lha /ERPLibre && \
|
||||
echo "${ERPLIBRE_VERSION}" && \
|
||||
./script/version/update_env_version.py --erplibre_version "${ERPLIBRE_VERSION}"
|
||||
./script/version/update_env_version.py --erplibre_version "${ERPLIBRE_VERSION}" --partial_install
|
||||
|
||||
RUN cd $ODOO_PREFIX && ls ./manifest -la && \
|
||||
ls -lha /ERPLibre && \
|
||||
|
|
|
|||
|
|
@ -112,6 +112,13 @@ You can change the docker directory by editing file `/etc/docker/daemon.json`
|
|||
```
|
||||
And restart docker service. You can delete or move all older locations of docker.
|
||||
|
||||
Or
|
||||
|
||||
Add `--data-root /second_drive/docker` like example following into file `/lib/systemd/system/docker.service` :
|
||||
```
|
||||
ExecStart=/usr/bin/dockerd --data-root /second_drive/docker -H fd:// --containerd=/run/containerd/containerd.sock
|
||||
```
|
||||
|
||||
# Update docker
|
||||
When building your docker with script
|
||||
> make docker_build_odoo_16
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@
|
|||
<project name="odoo-product-addons.git" path="addons.odoo14.0/Numigi_odoo-product-addons" remote="Numigi" groups="addons"/>
|
||||
<project name="odoo-project-addons.git" path="addons.odoo14.0/Numigi_odoo-project-addons" remote="Numigi" groups="addons"/>
|
||||
<project name="odoo-purchase-addons.git" path="addons.odoo14.0/Numigi_odoo-purchase-addons" remote="Numigi" groups="addons"/>
|
||||
<project name="odoo-stock-addons.git" path="addons.odoo14.0/Numigi_odoo-stock-addons" remote="Numigi" groups="addons"/>
|
||||
<project name="odoo-stock-addons.git" path="addons.odoo14.0/Numigi_odoo-stock-addons" remote="ERPLibre" revision="14.0_dev" groups="addons"/>
|
||||
<project name="odoo-survey-addons.git" path="addons.odoo14.0/Numigi_odoo-survey-addons" remote="Numigi" groups="addons"/>
|
||||
<project name="odoo-test-docs.git" path="doc/itpp-labs_odoo-test-docs" remote="itpp-labs" revision="master" groups="odoo"/>
|
||||
<project name="odoo-timesheet-addons.git" path="addons.odoo14.0/Numigi_odoo-timesheet-addons" remote="Numigi" groups="addons"/>
|
||||
|
|
@ -131,7 +131,7 @@
|
|||
<project name="server-brand.git" path="addons.odoo14.0/OCA_server-brand" remote="OCA" groups="addons"/>
|
||||
<project name="server-env.git" path="addons.odoo14.0/OCA_server-env" remote="OCA" groups="addons"/>
|
||||
<project name="server-tools.git" path="addons.odoo14.0/OCA_server-tools" remote="ERPLibre" revision="14.0_dev" groups="addons"/>
|
||||
<project name="server-ux.git" path="addons.odoo14.0/OCA_server-ux" remote="OCA" groups="addons"/>
|
||||
<project name="server-ux.git" path="addons.odoo14.0/OCA_server-ux" remote="ERPLibre" revision="14.0_dev" groups="addons"/>
|
||||
<project name="social.git" path="addons.odoo14.0/OCA_social" remote="ERPLibre" revision="14.0_dev" groups="addons"/>
|
||||
<project name="survey.git" path="addons.odoo14.0/OCA_survey" remote="OCA" groups="addons"/>
|
||||
<project name="stock-logistics-warehouse.git" path="addons.odoo14.0/OCA_stock-logistics-warehouse" remote="OCA" groups="addons"/>
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
<project name="ERPLibre_image_db.git" path="image_db" remote="ERPLibre" clone-depth="1" revision="main" groups="base"/>
|
||||
<project name="OpenHRMS.git" path="addons.odoo16.0/CybroOdoo_OpenHRMS" remote="CybroOdoo" groups="addons"/>
|
||||
<project name="CybroAddons.git" path="addons.odoo16.0/CybroOdoo_CybroAddons" remote="ERPLibre" revision="16.0_dev" groups="addons"/>
|
||||
<project name="CybroAddons.git" path="addons.odoo16.0/CybroOdoo_CybroAddons" remote="ERPLibre" clone-depth="1" revision="16.0_dev" groups="addons"/>
|
||||
<project name="account-analytic.git" path="addons.odoo16.0/OCA_account-analytic" remote="OCA" groups="addons"/>
|
||||
<project name="account-budgeting.git" path="addons.odoo16.0/OCA_account-budgeting" remote="OCA" groups="addons"/>
|
||||
<project name="account-closing.git" path="addons.odoo16.0/OCA_account-closing" remote="OCA" groups="addons"/>
|
||||
|
|
@ -70,6 +70,7 @@
|
|||
<project name="geospatial.git" path="addons.odoo16.0/OCA_geospatial" remote="OCA" groups="addons"/>
|
||||
<project name="helpdesk.git" path="addons.odoo16.0/OCA_helpdesk" remote="OCA" groups="addons"/>
|
||||
<project name="hr.git" path="addons.odoo16.0/OCA_hr" remote="OCA" groups="addons"/>
|
||||
<project name="hr-holidays.git" path="addons.odoo16.0/OCA_hr-holidays" remote="OCA" groups="addons"/>
|
||||
<project name="interface-github.git" path="addons.odoo16.0/OCA_interface-github" remote="OCA" groups="addons"/>
|
||||
<project name="knowledge.git" path="addons.odoo16.0/OCA_knowledge" remote="OCA" groups="addons"/>
|
||||
<project name="l10n-canada.git" path="addons.odoo16.0/OCA_l10n-canada" remote="OCA" groups="addons"/>
|
||||
|
|
@ -114,11 +115,12 @@
|
|||
<project name="server-env.git" path="addons.odoo16.0/OCA_server-env" remote="OCA" groups="addons"/>
|
||||
<project name="server-tools.git" path="addons.odoo16.0/OCA_server-tools" remote="ERPLibre" revision="ERPLibre/16.0" groups="addons"/>
|
||||
<project name="server-ux.git" path="addons.odoo16.0/OCA_server-ux" remote="OCA" groups="addons"/>
|
||||
<project name="shift-planning.git" path="addons.odoo16.0/OCA_shift-planning" remote="ERPLibre" revision="16.0_dev" groups="addons"/>
|
||||
<project name="social.git" path="addons.odoo16.0/OCA_social" remote="OCA" groups="addons"/>
|
||||
<project name="survey.git" path="addons.odoo16.0/OCA_survey" remote="ERPLibre" revision="16.0_dev" groups="addons"/>
|
||||
<project name="stock-logistics-warehouse.git" path="addons.odoo16.0/OCA_stock-logistics-warehouse" remote="OCA" groups="addons"/>
|
||||
<project name="storage.git" path="addons.odoo16.0/OCA_storage" remote="OCA" groups="addons"/>
|
||||
<project name="timesheet.git" path="addons.odoo16.0/OCA_timesheet" remote="OCA" groups="addons"/>
|
||||
<project name="timesheet.git" path="addons.odoo16.0/OCA_timesheet" remote="ERPLibre" revision="16.0-refactor-hr_timesheet_begin_end" groups="addons"/>
|
||||
<project name="vertical-association.git" path="addons.odoo16.0/OCA_vertical-association" remote="OCA" groups="addons"/>
|
||||
<project name="vertical-hotel.git" path="addons.odoo16.0/OCA_vertical-hotel" remote="OCA" groups="addons"/>
|
||||
<project name="vertical-isp.git" path="addons.odoo16.0/OCA_vertical-isp" remote="OCA" groups="addons"/>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -19,31 +19,32 @@ authors = [ "Mathieu Benoit <mathben@technolibre.ca>",]
|
|||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.8.20"
|
||||
acme = "^2.11.0"
|
||||
acme = "2.11.0"
|
||||
agithub = "^2.2.2"
|
||||
aiohttp = "^3.10.10"
|
||||
aiohttp = "3.10.10"
|
||||
aioshutil = "<1.2"
|
||||
argcomplete = "^3.5.1"
|
||||
anyio = ">=3.5"
|
||||
argcomplete = "^3.6.1"
|
||||
astor = "0.8.1"
|
||||
avalara = "^24.10.0"
|
||||
avalara = "^25.3.0"
|
||||
azure-identity = "1.13.0"
|
||||
azure-storage-blob = "12.16.0"
|
||||
babel = "2.9.1"
|
||||
beautifulsoup4 = "^4.12.3"
|
||||
beautifulsoup4 = "^4.13.3"
|
||||
bokeh = "2.3.1"
|
||||
boto3 = ">=1.20.41"
|
||||
cachetools = "^5.5.0"
|
||||
cachetools = "^5.5.2"
|
||||
chardet = "5.0.0"
|
||||
chromedriver-binary = "^132.0.6786.0.0"
|
||||
click = "^8.1.7"
|
||||
chromedriver-binary = "^136.0.7088.0.0"
|
||||
click = "^8.1.8"
|
||||
cloudflare = "2.20.0"
|
||||
colorama = "^0.4.6"
|
||||
contextvars = "^2.4"
|
||||
coverage = "7.6.1"
|
||||
cryptography = "39.0.1"
|
||||
css-html-prettify = "^2.5.5"
|
||||
cython = "^3.0.11"
|
||||
dateparser = "^1.2.0"
|
||||
cython = "^3.0.12"
|
||||
dateparser = "^1.2.1"
|
||||
ddt = "1.2.1"
|
||||
decorator = "4.3.0"
|
||||
dicttoxml = "^1.7.16"
|
||||
|
|
@ -51,10 +52,10 @@ dnspython = "2.6.1"
|
|||
docutils = "0.16.0"
|
||||
ebaysdk = "2.1.5"
|
||||
email-validator = "^2.2.0"
|
||||
emoji = "^2.14.0"
|
||||
endesive = "^2.17.3"
|
||||
emoji = "^2.14.1"
|
||||
endesive = "^2.18.5"
|
||||
extract-msg = "0.36.1"
|
||||
factur-x = "^3.1"
|
||||
factur-x = "<=3.1"
|
||||
fdfgen = "^0.16.1"
|
||||
feedparser = "6.0.10"
|
||||
flake8 = "<6.0.0"
|
||||
|
|
@ -65,19 +66,19 @@ geojson = "<3.0.0"
|
|||
gevent = "20.9.0"
|
||||
gitpython = "3.1.30"
|
||||
giturlparse = "^0.12.0"
|
||||
google-api-python-client = "^2.149.0"
|
||||
google-api-python-client = "^2.165.0"
|
||||
google-auth-httplib2 = "^0.2.0"
|
||||
google-auth-oauthlib = "^1.2.1"
|
||||
greenlet = "0.4.17"
|
||||
gst = "^0.1.0"
|
||||
gst = "^0.1.4"
|
||||
html2text = "^2024.2.26"
|
||||
idna = "2.6"
|
||||
img2pdf = "^0.5.1"
|
||||
idna = "2.8"
|
||||
img2pdf = "^0.6.0"
|
||||
invoice2data = "^0.4.5"
|
||||
iscompatible = "^0.1.1"
|
||||
isort = "<5.12.0"
|
||||
jinja2 = "2.11.3"
|
||||
josepy = "^1.14.0"
|
||||
josepy = "1.14.0"
|
||||
keystoneauth1 = "3.14.0"
|
||||
libsass = "0.17.0"
|
||||
lxml = "4.9.1"
|
||||
|
|
@ -91,17 +92,18 @@ numpy = "1.21.1"
|
|||
numpy-financial = "<=1.0.0"
|
||||
odoo-test-helper = "^2.1.1"
|
||||
odoorpc = "^0.10.1"
|
||||
ofxparse = "0.19"
|
||||
ofxparse = "0.21"
|
||||
openai = "^1.68.2"
|
||||
openpyxl = "^3.1.5"
|
||||
openupgradelib = "^3.7.1"
|
||||
openupgradelib = "^3.9.3"
|
||||
ovh = "1.1.2"
|
||||
packaging = "21.3"
|
||||
pandas = "1.3.5"
|
||||
paramiko = "^3.5.0"
|
||||
paramiko = "^3.5.1"
|
||||
passlib = "1.7.1"
|
||||
pathspec = "0.12.1"
|
||||
pdf2image = "^1.17.0"
|
||||
phonenumbers = "^8.13.47"
|
||||
phonenumbers = "^9.0.1"
|
||||
pillow = "9.3.0"
|
||||
plotly = "5.4.0"
|
||||
polib = "1.1.0"
|
||||
|
|
@ -114,12 +116,13 @@ py3o-formats = "^0.3"
|
|||
py3o-template = "^0.10.0"
|
||||
pycountry = "^24.6.1"
|
||||
pydot = "1.4.1"
|
||||
pyftpdlib = "^2.0.0"
|
||||
pyftpdlib = "^2.0.1"
|
||||
pygithub = "2.3.0"
|
||||
pygments = "2.7.4"
|
||||
pygobject = "3.44.1"
|
||||
pygount = "1.5.1"
|
||||
pyjwt = "2.5.0"
|
||||
pylint = "3.1.0"
|
||||
pyopenssl = "21.0.0"
|
||||
pypdf = ">=3.1.0,<5.0"
|
||||
pypdf2 = "1.27.9"
|
||||
|
|
@ -130,7 +133,7 @@ pysftp = "^0.2.9"
|
|||
python-chess = "^1.999"
|
||||
python-dateutil = "2.7.3"
|
||||
python-git = "^2018.2.1"
|
||||
python-jose = "^3.3.0"
|
||||
python-jose = "^3.4.0"
|
||||
python-json-logger = "0.1.5"
|
||||
python-keystoneclient = "3.22.0"
|
||||
python-ldap = "3.1.0"
|
||||
|
|
@ -151,17 +154,17 @@ reportlab = "3.6.5"
|
|||
requests = "2.28.1"
|
||||
retrying = "^1.3.4"
|
||||
roulier = "^1.1.1"
|
||||
selenium = "^4.25.0"
|
||||
selenium = "4.25.0"
|
||||
sentry-sdk = "<=1.9.0"
|
||||
setuptools = "65.5.1"
|
||||
shapely = "1.8.5"
|
||||
simplejson = "3.16.0"
|
||||
sphinx = "4.3.2"
|
||||
sphinx-intl = "^2.2.0"
|
||||
sphinx-intl = "2.2.0"
|
||||
sphinx-rtd-theme = "1.3.0"
|
||||
statsd = "3.2.1"
|
||||
toml = "^0.10.2"
|
||||
tqdm = "^4.66.5"
|
||||
tqdm = "^4.67.1"
|
||||
unicodecsv = "^0.14.1"
|
||||
unidecode = "1.0.23"
|
||||
unidiff = "^0.7.5"
|
||||
|
|
@ -170,21 +173,21 @@ uvloop = "^0.21.0"
|
|||
validators = "0.24.0"
|
||||
vobject = "0.9.6.1"
|
||||
voicent-python = "^1.0"
|
||||
webcolors = "^24.8.0"
|
||||
webcolors = "24.8.0"
|
||||
websocket-client = "^1.8.0"
|
||||
werkzeug = "0.16.1"
|
||||
wheel = "^0.44.0"
|
||||
wheel = "^0.45.1"
|
||||
win-unicode-console = "^0.5"
|
||||
xlrd = "1.1.0"
|
||||
xlsxwriter = "1.1.2"
|
||||
xlwt = "1.3"
|
||||
xmlformatter = "^0.2.6"
|
||||
xmlformatter = "^0.2.8"
|
||||
xmlrunner = "^1.7.7"
|
||||
xmlschema = "^3.4.2"
|
||||
xmlschema = "^3.4.5"
|
||||
xmltodict = "^0.14.2"
|
||||
zeep = "3.2.0"
|
||||
zipp = ">=3.6.0"
|
||||
zxcvbn = "^4.4.28"
|
||||
zxcvbn = "^4.5.0"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
websocket_client = "^1.1.0"
|
||||
|
|
@ -195,3 +198,4 @@ rev = "22.3.0"
|
|||
|
||||
[tool.poetry.dependencies.pylint-odoo]
|
||||
git = "https://github.com/oca/pylint-odoo.git"
|
||||
rev = "v9.1.3"
|
||||
|
|
|
|||
|
|
@ -20,30 +20,32 @@ authors = [ "Mathieu Benoit <mathben@technolibre.ca>",]
|
|||
[tool.poetry.dependencies]
|
||||
python = "^3.10.14"
|
||||
agithub = "^2.2.2"
|
||||
argcomplete = "^3.5.1"
|
||||
asana = "^5.0.10"
|
||||
argcomplete = "^3.6.2"
|
||||
asana = "^5.1.0"
|
||||
asn1crypto = "^1.5.1"
|
||||
astor = "^0.8.1"
|
||||
avalara = "^24.11.2"
|
||||
avalara = "^25.3.2"
|
||||
azure-identity = "1.13.0"
|
||||
azure-storage-blob = "12.16.0"
|
||||
babel = "2.9.1"
|
||||
base64io = "^1.0.3"
|
||||
beautifulsoup4 = "^4.12.3"
|
||||
beautifulsoup4 = "^4.13.3"
|
||||
bokeh = "3.1.1"
|
||||
boto3 = "1.26.7"
|
||||
bs4 = "^0.0.2"
|
||||
cachetools = "^5.5.0"
|
||||
cachetools = "^5.5.2"
|
||||
cairosvg = "^2.7.1"
|
||||
cerberus = "^1.3.7"
|
||||
chardet = "4.0.0"
|
||||
chromedriver-binary = "^137.0.7118.2.0"
|
||||
clicksend-client = "^5.0.78"
|
||||
cloudflare = "^3.1.0"
|
||||
cmake = "^3.31.1"
|
||||
cloudflare = "^4.1.0"
|
||||
cmake = "^4.0.0"
|
||||
colorama = "^0.4.6"
|
||||
countryinfo = "^0.1.2"
|
||||
cryptography = "3.4.8"
|
||||
cybersource-rest-client-python = "0.0.56"
|
||||
cython = "^3.0.11"
|
||||
cython = "^3.0.12"
|
||||
decorator = "4.4.2"
|
||||
dlib = "^19.24.6"
|
||||
docutils = "0.16"
|
||||
|
|
@ -51,44 +53,46 @@ dotty-dict = "^1.3.1"
|
|||
dropbox = "^12.0.2"
|
||||
ebaysdk = "2.1.5"
|
||||
email-validator = "^2.2.0"
|
||||
endesive = "^2.17.3"
|
||||
extract-msg = "^0.52.0"
|
||||
ezdxf = "^1.3.4"
|
||||
endesive = "^2.18.5"
|
||||
extract-msg = "^0.54.0"
|
||||
ezdxf = "^1.4.0"
|
||||
face-recognition = "^1.3.0"
|
||||
factur-x = "^3.1"
|
||||
factur-x = "^3.6"
|
||||
filetype = "^1.2.0"
|
||||
formio-data = "^2.1.0"
|
||||
freezegun = "0.3.15"
|
||||
fsspec = ">=2024.5.0"
|
||||
gdown = "^5.2.0"
|
||||
geocoder = "^1.38.1"
|
||||
geojson = "^3.1.0"
|
||||
geojson = "^3.2.0"
|
||||
geopy = "^2.4.1"
|
||||
gevent = "21.8.0"
|
||||
gevent = "21.12.0"
|
||||
gitpython = "3.1.30"
|
||||
giturlparse = "^0.12.0"
|
||||
googletrans-py = "4.0.0"
|
||||
greenlet = "1.1.2"
|
||||
gst = "^0.1.2"
|
||||
gst = "^0.1.4"
|
||||
httpagentparser = "1.8.1"
|
||||
hubspot-api-client = "10.0.0"
|
||||
idna = "2.10"
|
||||
iscompatible = "^0.1.1"
|
||||
isort = "^6.0.1"
|
||||
jinja2 = "2.11.3"
|
||||
keystoneauth1 = "5.0.0"
|
||||
libsass = "0.20.1"
|
||||
linkedin = "^0.1.5"
|
||||
lottie = "^0.7.1"
|
||||
lxml = "4.6.5"
|
||||
lxml-html-clean = "^0.4.1"
|
||||
mako = "^1.3.6"
|
||||
lxml-html-clean = "^0.4.2"
|
||||
mako = "^1.3.9"
|
||||
markupsafe = "1.1.1"
|
||||
matplotlib = "^3.9.2"
|
||||
matplotlib = "^3.10.1"
|
||||
mechanize = "^0.4.10"
|
||||
messagebird = "^2.2.0"
|
||||
mock = "^5.1.0"
|
||||
meteostat = "^1.6.8"
|
||||
mock = "^5.2.0"
|
||||
mpld3 = "0.5.9"
|
||||
mysqlclient = "^2.2.6"
|
||||
mysqlclient = "^2.2.7"
|
||||
nextcloud-api-wrapper = "^0.2.3"
|
||||
num2words = "0.5.13"
|
||||
numpy = ">=1.15"
|
||||
|
|
@ -98,21 +102,22 @@ odoo-test-helper = "^2.1.1"
|
|||
odoorpc = "^0.10.1"
|
||||
ofxparse = "0.21"
|
||||
ofxtools = "^0.9.5"
|
||||
openai = "^1.55.2"
|
||||
opencv-python = "^4.10.0.84"
|
||||
openai = "^1.72.0"
|
||||
opencv-python = "^4.11.0.86"
|
||||
openpyxl = "^3.1.5"
|
||||
openupgradelib = "^3.9.4"
|
||||
pandas = ">=0.25.3"
|
||||
paramiko = "^3.5.0"
|
||||
paramiko = "^3.5.1"
|
||||
passlib = "1.7.4"
|
||||
pathspec = "^0.12.1"
|
||||
pay-ccavenue = "^1.0.0"
|
||||
pdf2image = "^1.17.0"
|
||||
pdfminer = "^20191125"
|
||||
phonenumbers = "^8.13.50"
|
||||
phonenumbers = "^9.0.2"
|
||||
pillow = "9.0.1"
|
||||
plotly = "5.13.1"
|
||||
polib = "1.1.0"
|
||||
pre-commit = "^4.0.1"
|
||||
pre-commit = "^4.2.0"
|
||||
premailer = "^3.10.0"
|
||||
printnodeapi = "^0.2.0"
|
||||
prometheus-client = "0.15.0"
|
||||
|
|
@ -124,24 +129,26 @@ py3o-formats = "^0.3"
|
|||
py3o-template = "^0.10.0"
|
||||
pyaudio = "^0.2.14"
|
||||
pycountry = "^24.6.1"
|
||||
pydevd-odoo = "^1.2.2"
|
||||
pydifact = "^0.1.8"
|
||||
pydot = "1.4.2"
|
||||
pyfcm = "^2.0.7"
|
||||
pygithub = "^2.5.0"
|
||||
pyfcm = "^2.0.8"
|
||||
pygithub = "^2.6.1"
|
||||
pygobject = "3.44.1"
|
||||
pyjwt = "^2.10.1"
|
||||
pymssql = "<=2.2.5"
|
||||
pykeepass = "^4.1.1.post1"
|
||||
pymssql = "<=2.2.8"
|
||||
pyncclient = "^0.7"
|
||||
pyopenssl = "20.0.1"
|
||||
pypdf2 = "1.26.0"
|
||||
pyrfc6266 = "^1.0.2"
|
||||
pysaml2 = "^7.5.0"
|
||||
pysaml2 = "^7.5.2"
|
||||
pyserial = "3.5"
|
||||
pysftp = "^0.2.9"
|
||||
pytesseract = "^0.3.13"
|
||||
python-barcode = "^0.15.1"
|
||||
python-dateutil = "2.8.1"
|
||||
python-jose = "^3.3.0"
|
||||
python-dateutil = ">=2.8.2"
|
||||
python-jose = "^3.4.0"
|
||||
python-json-logger = "2.0.4"
|
||||
python-keystoneclient = "5.0.0"
|
||||
python-ldap = "3.4.0"
|
||||
|
|
@ -150,43 +157,44 @@ python-resize-image = "^1.1.20"
|
|||
python-slugify = "^8.0.4"
|
||||
python-stdnum = "1.16"
|
||||
python-swiftclient = "4.1.0"
|
||||
python-telegram-bot = "^21.7"
|
||||
pytz = "^2024.2"
|
||||
python-telegram-bot = "^22.0"
|
||||
pytz = "^2025.2"
|
||||
pyusb = "1.0.2"
|
||||
pyyaml = "6.0"
|
||||
pyzbar = "^0.1.9"
|
||||
pyzk = "^0.9"
|
||||
qrcode = "6.1"
|
||||
redis = "4.3.4"
|
||||
reportlab = "3.5.59"
|
||||
reportlab = "3.6.5"
|
||||
requests = "2.30.0"
|
||||
requests-toolbelt = "^1.0.0"
|
||||
responses = "^0.25.3"
|
||||
responses = "^0.25.7"
|
||||
retrying = "^1.3.4"
|
||||
rl-renderpm = "4.0.3"
|
||||
roulier = "^1.1.1"
|
||||
schwifty = "2024.4.0"
|
||||
selenium = "^4.27.1"
|
||||
selenium = "^4.31.0"
|
||||
sentry-sdk = "<=1.9.0"
|
||||
shapely = "^2.0.6"
|
||||
simplejson = "^3.19.3"
|
||||
spacy = "^3.8.2"
|
||||
shapely = "^2.1.0"
|
||||
simplejson = "^3.20.1"
|
||||
spacy = "3.8.2"
|
||||
speechrecognition = "3.10.0"
|
||||
sqlalchemy = "^2.0.36"
|
||||
sqlalchemy = "^2.0.40"
|
||||
statsd = "4.0.1"
|
||||
telesign = "^2.2.5"
|
||||
telnyx = "^2.1.3"
|
||||
telesign = "^2.2.6"
|
||||
telnyx = "^2.1.5"
|
||||
todoist-python = "^8.1.4"
|
||||
toml = "^0.10.2"
|
||||
tweepy = "^4.14.0"
|
||||
twilio = "^9.3.7"
|
||||
tweepy = "^4.15.0"
|
||||
twilio = "^9.5.2"
|
||||
unidecode = "^1.3.8"
|
||||
unidiff = "^0.7.5"
|
||||
urllib3 = "1.26.5"
|
||||
uvloop = "^0.21.0"
|
||||
validate-email = "^1.3"
|
||||
virtualenv = "20.30.0"
|
||||
vobject = "0.9.6.1"
|
||||
vonage = "^4.0.0"
|
||||
vonage = "^4.4.0"
|
||||
vonage-verify-v2 = "1.1.4"
|
||||
werkzeug = "2.0.2"
|
||||
wheel = "^0.45.1"
|
||||
|
|
@ -202,7 +210,3 @@ websocket_client = "^1.1.0"
|
|||
[tool.poetry.dependencies.black]
|
||||
git = "https://github.com/psf/black.git"
|
||||
rev = "24.8.0"
|
||||
|
||||
[tool.poetry.dependencies.openupgradelib]
|
||||
git = "https://github.com/OCA/openupgradelib"
|
||||
rev = "master"
|
||||
|
|
|
|||
|
|
@ -35,12 +35,11 @@ python-git
|
|||
voicent-python
|
||||
python-swiftclient
|
||||
python-keystoneclient
|
||||
coverage
|
||||
|
||||
# For logical test
|
||||
docutils==0.16.0
|
||||
flake8<6.0.0
|
||||
git+https://github.com/oca/pylint-odoo.git
|
||||
git+https://github.com/oca/pylint-odoo.git@v9.1.3
|
||||
# oca-maintainers-tools
|
||||
# git+https://github.com/OCA/maintainer-tools.git#egg=oca-maintainers-tools
|
||||
xmlformatter
|
||||
|
|
@ -98,7 +97,6 @@ geojson<3.0.0
|
|||
regex==2022.3.2
|
||||
pygount==1.5.1
|
||||
pysaml2==7.2.1
|
||||
gevent==1.5.0
|
||||
freezegun==0.3.15
|
||||
pyopenssl==21.0.0
|
||||
ovh==1.1.2
|
||||
|
|
@ -106,6 +104,16 @@ sphinx-rtd-theme==1.3.0
|
|||
sphinx_rtd_theme==1.3.0
|
||||
dnspython==2.6.1
|
||||
coverage==7.6.1
|
||||
webcolors==24.8.0
|
||||
aiohttp==3.10.10
|
||||
josepy==1.14.0
|
||||
acme==2.11.0
|
||||
sphinx-intl==2.2.0
|
||||
selenium==4.25.0
|
||||
anyio>=3.5
|
||||
openai
|
||||
idna==2.8
|
||||
pylint==3.1.0
|
||||
|
||||
# asyncio
|
||||
aioshutil<1.2
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ selenium
|
|||
# mmg # depend on weasyprint 59.0 and depend on old version pillow 9.0.1
|
||||
uvloop
|
||||
python-randomword-fr
|
||||
isort
|
||||
pykeepass
|
||||
|
||||
# For OSX
|
||||
cython
|
||||
|
|
@ -51,7 +53,7 @@ pre-commit
|
|||
# For python 3.10 from odoo/requirements.txt, poetry_update.py cannot support python_version
|
||||
cryptography==3.4.8
|
||||
freezegun==0.3.15
|
||||
gevent==21.8.0
|
||||
gevent==21.12.0
|
||||
greenlet==1.1.2
|
||||
Jinja2==2.11.3
|
||||
libsass==0.20.1
|
||||
|
|
@ -66,7 +68,7 @@ PyPDF2==1.26.0
|
|||
python-ldap==3.4.0
|
||||
pyusb==1.0.2
|
||||
requests==2.30.0
|
||||
reportlab==3.5.59
|
||||
reportlab==3.6.5
|
||||
urllib3==1.26.5
|
||||
Werkzeug==2.0.2
|
||||
xlrd==1.2.0
|
||||
|
|
@ -83,3 +85,18 @@ hubspot-api-client==10.0.0
|
|||
|
||||
# Optional Odoo
|
||||
pdfminer
|
||||
|
||||
# Optional PyDev
|
||||
pydevd-odoo
|
||||
|
||||
# For fixing module ocr_data_retrieval check file ocr_data_retrieval/models/ocr_data_template.py
|
||||
spacy==3.8.2
|
||||
|
||||
# Fix update dateutil from odoo
|
||||
python-dateutil>=2.8.2
|
||||
|
||||
# Extra module
|
||||
meteostat
|
||||
|
||||
# Force upgrade package to fix Ubuntu 25.04
|
||||
virtualenv==20.30.0
|
||||
|
|
|
|||
|
|
@ -5,4 +5,4 @@ if [ $# -lt 1 ]; then
|
|||
exit 1
|
||||
fi
|
||||
source ./.venv/bin/activate
|
||||
python3 ./odoo/odoo-bin -c ./config.conf --limit-time-real 99999 --limit-time-cpu 99999 --stop-after-init -i user_test,disable_mail_server,disable_auto_backup --dev prod -d $@
|
||||
python3 ./odoo/odoo-bin -c ./config.conf --limit-time-real 99999 --limit-time-cpu 99999 --no-http --stop-after-init -i user_test,disable_mail_server,disable_auto_backup --dev prod -d $@
|
||||
|
|
|
|||
|
|
@ -67,15 +67,15 @@ echo $POETRY_VERSION
|
|||
if [ "$IS_RELEASE_ALPHA" == true ]
|
||||
then
|
||||
# Add commit hash when release alpha
|
||||
ERPLIBRE_VERSION="${ERPLIBRE_VERSION}_ALPHA_$(git rev-parse --short HEAD)"
|
||||
ERPLIBRE_VERSION="${ERPLIBRE_VERSION}_ALPHA_odoo_${ODOO_VERSION}_$(git rev-parse --short HEAD)"
|
||||
elif [ "$IS_RELEASE_BETA" == true ]
|
||||
then
|
||||
# Add commit hash when release beta
|
||||
ERPLIBRE_VERSION="${ERPLIBRE_VERSION}_BETA_$(git rev-parse --short HEAD)"
|
||||
ERPLIBRE_VERSION="${ERPLIBRE_VERSION}_BETA_odoo_${ODOO_VERSION}_$(git rev-parse --short HEAD)"
|
||||
elif [ "$IS_RELEASE" == false ]
|
||||
then
|
||||
# Add commit hash when not a release
|
||||
ERPLIBRE_VERSION="${ERPLIBRE_VERSION}_$(git rev-parse --short HEAD)"
|
||||
ERPLIBRE_VERSION="${ERPLIBRE_VERSION}_odoo_${ODOO_VERSION}_$(git rev-parse --short HEAD)"
|
||||
fi
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ if [[ ${EL_MINIMAL_ADDONS} = "False" ]]; then
|
|||
printf "${EL_HOME}/addons.odoo${EL_ODOO_VERSION}/CybroOdoo_CybroAddons," >> "${EL_CONFIG_FILE}"
|
||||
printf "${EL_HOME}/addons.odoo${EL_ODOO_VERSION}/CybroOdoo_OpenHRMS," >> "${EL_CONFIG_FILE}"
|
||||
printf "${EL_HOME}/addons.odoo${EL_ODOO_VERSION}/ERPLibre_erplibre_addons," >> "${EL_CONFIG_FILE}"
|
||||
printf "${EL_HOME}/addons.odoo${EL_ODOO_VERSION}/MathBenTech_odoo-business-spending-management-quebec-canada," >> "${EL_CONFIG_FILE}"
|
||||
printf "${EL_HOME}/addons.odoo${EL_ODOO_VERSION}/OCA_account-analytic," >> "${EL_CONFIG_FILE}"
|
||||
printf "${EL_HOME}/addons.odoo${EL_ODOO_VERSION}/OCA_account-budgeting," >> "${EL_CONFIG_FILE}"
|
||||
printf "${EL_HOME}/addons.odoo${EL_ODOO_VERSION}/OCA_account-closing," >> "${EL_CONFIG_FILE}"
|
||||
|
|
@ -68,6 +69,7 @@ if [[ ${EL_MINIMAL_ADDONS} = "False" ]]; then
|
|||
printf "${EL_HOME}/addons.odoo${EL_ODOO_VERSION}/OCA_geospatial," >> "${EL_CONFIG_FILE}"
|
||||
printf "${EL_HOME}/addons.odoo${EL_ODOO_VERSION}/OCA_helpdesk," >> "${EL_CONFIG_FILE}"
|
||||
printf "${EL_HOME}/addons.odoo${EL_ODOO_VERSION}/OCA_hr," >> "${EL_CONFIG_FILE}"
|
||||
printf "${EL_HOME}/addons.odoo${EL_ODOO_VERSION}/OCA_hr-holidays," >> "${EL_CONFIG_FILE}"
|
||||
printf "${EL_HOME}/addons.odoo${EL_ODOO_VERSION}/OCA_interface-github," >> "${EL_CONFIG_FILE}"
|
||||
printf "${EL_HOME}/addons.odoo${EL_ODOO_VERSION}/OCA_knowledge," >> "${EL_CONFIG_FILE}"
|
||||
printf "${EL_HOME}/addons.odoo${EL_ODOO_VERSION}/OCA_l10n-canada," >> "${EL_CONFIG_FILE}"
|
||||
|
|
@ -99,6 +101,7 @@ if [[ ${EL_MINIMAL_ADDONS} = "False" ]]; then
|
|||
printf "${EL_HOME}/addons.odoo${EL_ODOO_VERSION}/OCA_server-env," >> "${EL_CONFIG_FILE}"
|
||||
printf "${EL_HOME}/addons.odoo${EL_ODOO_VERSION}/OCA_server-tools," >> "${EL_CONFIG_FILE}"
|
||||
printf "${EL_HOME}/addons.odoo${EL_ODOO_VERSION}/OCA_server-ux," >> "${EL_CONFIG_FILE}"
|
||||
printf "${EL_HOME}/addons.odoo${EL_ODOO_VERSION}/OCA_shift-planning," >> "${EL_CONFIG_FILE}"
|
||||
printf "${EL_HOME}/addons.odoo${EL_ODOO_VERSION}/OCA_social," >> "${EL_CONFIG_FILE}"
|
||||
printf "${EL_HOME}/addons.odoo${EL_ODOO_VERSION}/OCA_stock-logistics-warehouse," >> "${EL_CONFIG_FILE}"
|
||||
printf "${EL_HOME}/addons.odoo${EL_ODOO_VERSION}/OCA_storage," >> "${EL_CONFIG_FILE}"
|
||||
|
|
|
|||
62
script/install/install_arch_linux.sh
Executable file
62
script/install/install_arch_linux.sh
Executable file
|
|
@ -0,0 +1,62 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
install_package() {
|
||||
local package_name=$1
|
||||
|
||||
# Check package is already installed
|
||||
if pacman -Qs "$package_name" > /dev/null; then
|
||||
echo "$package_name is already installed."
|
||||
else
|
||||
echo "Installation of package $package_name..."
|
||||
yes|yay -S "$package_name"
|
||||
fi
|
||||
}
|
||||
|
||||
# Odoo installation
|
||||
install_package postgis
|
||||
install_package postgresql
|
||||
install_package mariadb
|
||||
install_package libev
|
||||
install_package wkhtmltopdf
|
||||
|
||||
echo "Need password to create symbolic link, create postgres user and install npm :"
|
||||
sudo ln -fs /usr/lib/libldap.so /usr/lib/libldap_r.so
|
||||
|
||||
sudo su - postgres -c "createuser -s ${EL_USER}" 2>/dev/null || true
|
||||
|
||||
echo -e "\n---- Update NPM ----"
|
||||
install_package npm
|
||||
|
||||
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 ----"
|
||||
npm install
|
||||
retVal=$?
|
||||
if [[ $retVal -ne 0 ]]; then
|
||||
echo "npm install prettier + plugin-xml installation error."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# TODO install nginx
|
||||
|
||||
# ERPLibre installation
|
||||
install_package cmake
|
||||
install_package parallel
|
||||
install_package tk
|
||||
|
|
@ -14,7 +14,7 @@ EL_USER=${USER}
|
|||
UBUNTU_VERSION=$(lsb_release -rs)
|
||||
DEBIAN_VERSION=$(lsb_release -cs)
|
||||
OS=$(lsb_release -si)
|
||||
if [ "24.04" == "${UBUNTU_VERSION}" ] || [ "24.10" == "${UBUNTU_VERSION}" ] || [ "23.10" == "${UBUNTU_VERSION}" ] || [ "23.04" == "${UBUNTU_VERSION}" ] || [ "22.10" == "${UBUNTU_VERSION}" ] || [ "22.04" == "${UBUNTU_VERSION}" ]; then
|
||||
if [ "25.04" == "${UBUNTU_VERSION}" ] || [ "24.04" == "${UBUNTU_VERSION}" ] || [ "24.10" == "${UBUNTU_VERSION}" ] || [ "23.10" == "${UBUNTU_VERSION}" ] || [ "23.04" == "${UBUNTU_VERSION}" ] || [ "22.10" == "${UBUNTU_VERSION}" ] || [ "22.04" == "${UBUNTU_VERSION}" ]; then
|
||||
WKHTMLTOX_X64=https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.jammy_amd64.deb
|
||||
elif [ "20.04" == "${UBUNTU_VERSION}" ]; then
|
||||
WKHTMLTOX_X64=https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb
|
||||
|
|
|
|||
|
|
@ -1,20 +1,21 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
if [[ "${OSTYPE}" == "linux-gnu" ]]; then
|
||||
OS=$(lsb_release -si)
|
||||
VERSION=$(cat /etc/issue)
|
||||
if [[ "${OS}" == *"Ubuntu"* ]]; then
|
||||
if [[ "${VERSION}" == Ubuntu\ 18.04* || "${VERSION}" == Ubuntu\ 20.04* || "${VERSION}" == Ubuntu\ 22.04* || "${VERSION}" == Ubuntu\ 22.10* || "${VERSION}" == Ubuntu\ 23.04* || "${VERSION}" == Ubuntu\ 23.10* || "${VERSION}" == Ubuntu\ 24.04* ]]; then
|
||||
source /etc/os-release
|
||||
if [[ "${ID}" == "ubuntu" ]]; then
|
||||
if [[ "${VERSION_ID}" == "18.04" || "${VERSION_ID}" == "20.04" || "${VERSION_ID}" == "22.04" || "${VERSION_ID}" == "22.10" || "${VERSION_ID}" == "23.04" || "${VERSION_ID}" == "23.10" || "${VERSION_ID}" == "24.04" || "${VERSION_ID}" == "25.04" ]]; then
|
||||
echo "\n---- linux-gnu installation process started ----"
|
||||
./script/install/install_debian_dependency.sh
|
||||
else
|
||||
echo "Your version is not supported, only support 18.04, 20.04 and 22.04 - 24.04 : ${VERSION}"
|
||||
echo "Your version is not supported, only support 18.04, 20.04 and 22.04 - 24.04, 25.04 : ${VERSION_ID}"
|
||||
fi
|
||||
elif [[ "${OS}" == *"Debian"* ]]; then
|
||||
elif [[ "${ID}" == "debian" ]]; then
|
||||
./script/install/install_debian_dependency.sh
|
||||
elif [[ "${ID}" == "arch" ]]; then
|
||||
./script/install/install_arch_linux.sh
|
||||
else
|
||||
./script/install/install_debian_dependency.sh
|
||||
echo "Your Linux system is not supported, only support Ubuntu 18.04 or Ubuntu 20.04 or Ubuntu 22.04 - Ubuntu 23.10 - Ubuntu 24.04 ."
|
||||
echo "Your Linux system is not supported, only support Ubuntu 18.04 or Ubuntu 20.04 or Ubuntu 22.04 - Ubuntu 23.10 - Ubuntu 24.04, Ubuntu 25.04 ."
|
||||
fi
|
||||
elif [[ "${OSTYPE}" == "darwin"* ]]; then
|
||||
echo "\n---- Darwin installation process started ----"
|
||||
|
|
|
|||
|
|
@ -105,6 +105,10 @@ def combine_requirements(config):
|
|||
lst_requirements_file = get_lst_requirements_txt()
|
||||
# lst_requirements_with_condition = set()
|
||||
# dct_special_condition = defaultdict(list)
|
||||
|
||||
if not os.path.isfile(priority_filename_requirement):
|
||||
_logger.error(f"File {priority_filename_requirement} not found.")
|
||||
|
||||
dct_requirements_module_filename = defaultdict(list)
|
||||
for requirements_filename in lst_requirements_file:
|
||||
with open(requirements_filename, "r") as f:
|
||||
|
|
|
|||
51
script/selenium/combine_video.sh
Executable file
51
script/selenium/combine_video.sh
Executable file
|
|
@ -0,0 +1,51 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Get two last .webm file
|
||||
videos=($(ls -t *.webm | head -n 2))
|
||||
|
||||
if [ ${#videos[@]} -ne 2 ]; then
|
||||
echo "Error : you need two files .webm in root directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
timestamp=$(date +"%Y%m%d_%H%M%S")
|
||||
output_name="output_${timestamp}.webm"
|
||||
|
||||
video1="${videos[0]}"
|
||||
video2="${videos[1]}"
|
||||
|
||||
echo "first video ${video1}"
|
||||
echo "second video ${video2}"
|
||||
|
||||
# Obtenez les durées des vidéos
|
||||
duration1=$(ffmpeg -i "$video1" 2>&1 | grep 'Duration' | cut -d ' ' -f 4 | tr -d ,)
|
||||
duration2=$(ffmpeg -i "$video2" 2>&1 | grep 'Duration' | cut -d ' ' -f 4 | tr -d ,)
|
||||
echo "duration 1 : ${duration1}"
|
||||
echo "duration 2 : ${duration2}"
|
||||
|
||||
# Convertir les durées en secondes
|
||||
duration1_sec=$(echo "$duration1" | awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }')
|
||||
duration2_sec=$(echo "$duration2" | awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }')
|
||||
echo "duration 1 sec : ${duration1_sec}"
|
||||
echo "duration 2 sec : ${duration2_sec}"
|
||||
|
||||
# Déterminer la durée la plus courte
|
||||
min_duration=$(echo "$duration1_sec $duration2_sec" | awk '{print ($1 < $2) ? $1 : $2}')
|
||||
echo "Min duration : ${min_duration}"
|
||||
|
||||
# Créez la sortie
|
||||
#output_name="output.mp4"
|
||||
|
||||
# Utiliser ffmpeg pour couper et empiler les vidéos
|
||||
#ffmpeg -i "$video1" -i "$video2" -filter_complex "
|
||||
# [0:v]trim=start=0:end=$min_duration,setpts=PTS-STARTPTS[v0];
|
||||
# [1:v]trim=start=0:end=$min_duration,setpts=PTS-STARTPTS[v1];
|
||||
# [v0][v1]hstack=inputs=2" "$output_name"
|
||||
|
||||
#echo "Les vidéos ont été combinées en $output_name"
|
||||
|
||||
ffmpeg -i "${videos[0]}" -i "${videos[1]}" -filter_complex "hstack=inputs=2" "${output_name}"
|
||||
# with normalize size video
|
||||
#ffmpeg -i "${videos[0]}" -i "${videos[1]}" -filter_complex "[0:v]scale=320:240[v0]; [1:v]scale=320:240[v1]; [v0][v1]hstack=inputs=2" "${output_name}"
|
||||
|
||||
echo "${output_name}"
|
||||
|
|
@ -2,10 +2,11 @@
|
|||
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
import web_login
|
||||
import sys
|
||||
|
||||
import selenium_lib
|
||||
import web_login
|
||||
|
||||
|
||||
def run(config, selenium_tool):
|
||||
|
|
|
|||
|
|
@ -2,29 +2,46 @@
|
|||
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
||||
|
||||
from randomwordfr import RandomWordFr
|
||||
import re
|
||||
import datetime
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
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
|
||||
from selenium.webdriver.firefox.service import Service
|
||||
from subprocess import getoutput
|
||||
|
||||
from randomwordfr import RandomWordFr
|
||||
from selenium import webdriver
|
||||
from selenium.common.exceptions import (
|
||||
ElementClickInterceptedException,
|
||||
TimeoutException,
|
||||
)
|
||||
from selenium.webdriver import ActionChains
|
||||
from selenium.webdriver.common.actions.wheel_input import ScrollOrigin
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.common.keys import Keys
|
||||
from selenium.webdriver.firefox.service import Service
|
||||
from selenium.webdriver.remote.webelement import WebElement
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
|
||||
|
||||
class SeleniumLib(object):
|
||||
def __init__(self, config):
|
||||
self.config = config
|
||||
self.video_recorder = None
|
||||
self.filename = "video_" + time.strftime("%Y_%m_%d-%H_%M_%S") + ".webm"
|
||||
if self.config.video_suffix:
|
||||
self.filename = (
|
||||
f"video_{self.config.video_suffix}_"
|
||||
+ time.strftime("%Y_%m_%d-%H_%M_%S")
|
||||
+ ".webm"
|
||||
)
|
||||
else:
|
||||
self.filename = (
|
||||
"video_" + time.strftime("%Y_%m_%d-%H_%M_%S") + ".webm"
|
||||
)
|
||||
self.driver = None
|
||||
|
||||
def configure(self):
|
||||
def configure(self, ignore_open_web=False):
|
||||
# Configuration pour lancer Firefox en mode de navigation privée
|
||||
firefox_options = webdriver.FirefoxOptions()
|
||||
if not self.config.not_private_mode:
|
||||
|
|
@ -70,6 +87,7 @@ class SeleniumLib(object):
|
|||
|
||||
# Ajout de l'enregistrement
|
||||
if self.config.record_mode:
|
||||
# Create recording
|
||||
new_path = os.path.normpath(
|
||||
os.path.join(os.path.dirname(__file__), "..", "..")
|
||||
)
|
||||
|
|
@ -121,7 +139,8 @@ class SeleniumLib(object):
|
|||
)
|
||||
|
||||
# Ouvrez la page web
|
||||
self.driver.get(f"{self.config.url}/web")
|
||||
if not ignore_open_web:
|
||||
self.driver.get(f"{self.config.url}/web")
|
||||
|
||||
# Close tab opening by DarkReader
|
||||
if self.config.not_private_mode and not self.config.no_dark_mode:
|
||||
|
|
@ -150,6 +169,7 @@ class SeleniumLib(object):
|
|||
)
|
||||
)
|
||||
button.click()
|
||||
return button
|
||||
|
||||
def get_element(self, by: str = By.ID, value: str = None, timeout=5):
|
||||
wait = WebDriverWait(self.driver, timeout)
|
||||
|
|
@ -164,6 +184,125 @@ class SeleniumLib(object):
|
|||
|
||||
return ele[0]
|
||||
|
||||
def get_element_not_visible(
|
||||
self, by: str = By.ID, value: str = None, timeout=5
|
||||
):
|
||||
wait = WebDriverWait(self.driver, timeout)
|
||||
ele = wait.until(
|
||||
EC.presence_of_element_located(
|
||||
(
|
||||
by,
|
||||
value,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
return ele
|
||||
|
||||
def get_elements_not_visible(
|
||||
self, by: str = By.ID, value: str = None, timeout=5
|
||||
):
|
||||
wait = WebDriverWait(self.driver, timeout)
|
||||
ele = wait.until(
|
||||
EC.presence_of_all_elements_located(
|
||||
(
|
||||
by,
|
||||
value,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
return ele
|
||||
|
||||
def get_all_element(self, by: str = By.ID, value: str = None, timeout=5):
|
||||
wait = WebDriverWait(self.driver, timeout)
|
||||
ele = wait.until(
|
||||
EC.visibility_of_all_elements_located(
|
||||
(
|
||||
by,
|
||||
value,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
return ele
|
||||
|
||||
def wait_new_element_and_click(
|
||||
self,
|
||||
by: str = By.ID,
|
||||
value: str = None,
|
||||
delay_wait=1,
|
||||
timeout=5,
|
||||
inject_cursor=False,
|
||||
):
|
||||
new_element = self.wait_new_element(
|
||||
by=by, value=value, delay_wait=delay_wait, timeout=timeout
|
||||
)
|
||||
if new_element:
|
||||
if inject_cursor:
|
||||
self.inject_cursor()
|
||||
self.click_with_mouse_move(element=new_element, no_scroll=True)
|
||||
return new_element
|
||||
|
||||
def wait_new_element(
|
||||
self,
|
||||
by: str = By.ID,
|
||||
value: str = None,
|
||||
delay_wait=1,
|
||||
timeout=5,
|
||||
timeout_wait=None,
|
||||
):
|
||||
element = None
|
||||
# TODO support timeout_wait
|
||||
while element is None:
|
||||
time.sleep(delay_wait)
|
||||
try:
|
||||
element = self.get_element(by, value, timeout)
|
||||
except TimeoutException as e:
|
||||
pass
|
||||
print(f"Waiting {delay_wait} seconds after value '{value}'")
|
||||
return element
|
||||
|
||||
def wait_add_new_element_and_click(
|
||||
self, by: str = By.ID, value: str = None, delay_wait=1, timeout=5
|
||||
):
|
||||
new_element = self.wait_add_new_element(
|
||||
by=by, value=value, delay_wait=delay_wait, timeout=timeout
|
||||
)
|
||||
self.click_with_mouse_move(element=new_element, no_scroll=True)
|
||||
return new_element
|
||||
|
||||
def wait_add_new_element(
|
||||
self, by: str = By.ID, value: str = None, delay_wait=1, timeout=5
|
||||
):
|
||||
all_element_init = self.get_all_element(by=by, value=value)
|
||||
len_all_element_init = len(all_element_init)
|
||||
len_all_element = len_all_element_init
|
||||
all_element = []
|
||||
while len_all_element_init == len_all_element:
|
||||
time.sleep(delay_wait)
|
||||
all_element = self.get_all_element(by=by, value=value)
|
||||
len_all_element = len(all_element)
|
||||
print(f"Waiting {delay_wait} seconds after value '{value}'")
|
||||
new_element = all_element[-1]
|
||||
return new_element
|
||||
|
||||
def wait_increment_number_text_and_click(
|
||||
self, by: str = By.ID, value: str = None, delay_wait=1, timeout=5
|
||||
):
|
||||
element_init = self.get_element(by=by, value=value, timeout=timeout)
|
||||
actual_number = int(element_init.text)
|
||||
number_goal = actual_number + 1
|
||||
while actual_number < number_goal:
|
||||
time.sleep(delay_wait)
|
||||
element_goal = self.get_element(
|
||||
by=by, value=value, timeout=timeout
|
||||
)
|
||||
actual_number = int(element_goal.text)
|
||||
print(f"Waiting {delay_wait} seconds after value '{value}'")
|
||||
self.click_with_mouse_move(element=element_init, no_scroll=True)
|
||||
return element_init
|
||||
|
||||
def click_with_mouse_move(
|
||||
self,
|
||||
by: str = By.ID,
|
||||
|
|
@ -172,9 +311,15 @@ class SeleniumLib(object):
|
|||
no_scroll: bool = False,
|
||||
viewport_ele_by: str = By.ID,
|
||||
viewport_ele_value: str = None,
|
||||
element: WebElement = None,
|
||||
with_index: bool = False,
|
||||
index_of_list: int = 0,
|
||||
):
|
||||
# ele = self.driver.find_element(by, value)
|
||||
ele = self.get_element(by, value, timeout)
|
||||
if element:
|
||||
ele = element
|
||||
else:
|
||||
ele = self.get_element(by, value, timeout)
|
||||
if not no_scroll:
|
||||
viewport_ele = None
|
||||
if viewport_ele_value:
|
||||
|
|
@ -182,18 +327,67 @@ class SeleniumLib(object):
|
|||
viewport_ele_by, viewport_ele_value, timeout
|
||||
)
|
||||
self.scrollto_element(ele, viewport_ele=viewport_ele)
|
||||
# ActionChains(self.driver).move_to_element(ele).click().perform()
|
||||
ActionChains(self.driver).move_to_element(ele).perform()
|
||||
time.sleep(self.config.selenium_default_delay)
|
||||
wait = WebDriverWait(self.driver, timeout)
|
||||
button = wait.until(
|
||||
EC.element_to_be_clickable(
|
||||
(
|
||||
by,
|
||||
value,
|
||||
if element:
|
||||
button = wait.until(EC.element_to_be_clickable(element))
|
||||
else:
|
||||
if with_index:
|
||||
buttons = wait.until(
|
||||
EC.presence_of_all_elements_located(
|
||||
(
|
||||
by,
|
||||
value,
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
button.click()
|
||||
button = buttons[index_of_list]
|
||||
else:
|
||||
button = wait.until(
|
||||
EC.element_to_be_clickable(
|
||||
(
|
||||
by,
|
||||
value,
|
||||
)
|
||||
)
|
||||
)
|
||||
try:
|
||||
button.click()
|
||||
except ElementClickInterceptedException as e:
|
||||
try:
|
||||
print(e)
|
||||
self.driver.execute_script(
|
||||
"arguments[0].scrollIntoView(true);", button
|
||||
)
|
||||
button.click()
|
||||
except ElementClickInterceptedException as e:
|
||||
print(e)
|
||||
self.driver.execute_script("arguments[0].click();", button)
|
||||
return button
|
||||
|
||||
def click_canvas_form(
|
||||
self,
|
||||
by: str = By.ID,
|
||||
value: str = None,
|
||||
timeout: int = 5,
|
||||
form="carre",
|
||||
):
|
||||
|
||||
# ele = self.driver.find_element(by, value)
|
||||
ele = self.get_element(by, value, timeout)
|
||||
actions = ActionChains(self.driver)
|
||||
actions.move_to_element_with_offset(ele, -50, -50)
|
||||
actions.click_and_hold()
|
||||
if form == "carre":
|
||||
actions.move_by_offset(50, 0)
|
||||
actions.move_by_offset(0, 50)
|
||||
actions.move_by_offset(-50, 0)
|
||||
actions.move_by_offset(0, -50)
|
||||
|
||||
actions.release()
|
||||
actions.perform()
|
||||
|
||||
def input_text_with_mouse_move(
|
||||
self,
|
||||
|
|
@ -216,6 +410,8 @@ class SeleniumLib(object):
|
|||
)
|
||||
self.scrollto_element(ele, viewport_ele=viewport_ele)
|
||||
ActionChains(self.driver).move_to_element(ele).perform()
|
||||
|
||||
# Write content
|
||||
ele.send_keys(text_value)
|
||||
if delay_after > 0:
|
||||
time.sleep(delay_after)
|
||||
|
|
@ -346,7 +542,50 @@ class SeleniumLib(object):
|
|||
cursor.style.top = e.pageY - 5 + 'px';
|
||||
});
|
||||
"""
|
||||
self.driver.execute_script(cursor_script)
|
||||
try:
|
||||
try:
|
||||
self.driver.execute_script(cursor_script)
|
||||
except Exception as e:
|
||||
time.sleep(1)
|
||||
print("Error execute script cursor, wait 1 second")
|
||||
self.driver.execute_script(cursor_script)
|
||||
except Exception as e:
|
||||
time.sleep(3)
|
||||
print("Error execute script cursor, wait 3 second")
|
||||
self.driver.execute_script(cursor_script)
|
||||
|
||||
def scenario_create_new_account_with_random_user(
|
||||
self, show_cursor=False, def_action_before_submit=None
|
||||
):
|
||||
# Click no account
|
||||
if show_cursor:
|
||||
self.inject_cursor()
|
||||
self.click_with_mouse_move(
|
||||
By.XPATH, "/html/body/div[1]/main/div/form/div[3]/div[1]/a[1]"
|
||||
)
|
||||
|
||||
# Trouvez les éléments du formulaire
|
||||
if show_cursor:
|
||||
self.inject_cursor()
|
||||
|
||||
# Remplissez le courriel et le mot de passe
|
||||
first_name = self.get_french_word_no_space_no_accent()
|
||||
password = first_name.lower()
|
||||
second_name = self.get_french_word_no_space_no_accent()
|
||||
full_name = f"{first_name} {second_name}"
|
||||
domain = self.get_french_word_no_space_no_accent().lower()
|
||||
|
||||
self.input_text_with_mouse_move(
|
||||
By.NAME, "login", f"{password}@{domain}.com"
|
||||
)
|
||||
self.input_text_with_mouse_move(By.NAME, "name", full_name)
|
||||
self.input_text_with_mouse_move(By.NAME, "password", password)
|
||||
self.input_text_with_mouse_move(By.NAME, "confirm_password", password)
|
||||
if def_action_before_submit:
|
||||
def_action_before_submit()
|
||||
self.click_with_mouse_move(
|
||||
By.XPATH, "/html/body/div[1]/main/div/form/div[6]/button"
|
||||
)
|
||||
|
||||
def open_tab(self, url):
|
||||
# Open a new window
|
||||
|
|
@ -364,9 +603,157 @@ class SeleniumLib(object):
|
|||
except Exception:
|
||||
print("Chatbot cannot be found, stop searching it.")
|
||||
|
||||
# Website
|
||||
def odoo_website_menu_click(self, from_text=""):
|
||||
if not from_text:
|
||||
raise Exception(
|
||||
"Cannot click, empty parameter from method"
|
||||
" odoo_website_menu_click"
|
||||
)
|
||||
button = self.click_with_mouse_move(
|
||||
By.LINK_TEXT, from_text, timeout=30
|
||||
)
|
||||
return button
|
||||
|
||||
# Web
|
||||
def odoo_fill_widget_char(self, field_name, text):
|
||||
# Type input
|
||||
text_field = WebDriverWait(self.driver, 10).until(
|
||||
EC.presence_of_element_located((By.NAME, field_name))
|
||||
)
|
||||
text_field.send_keys(text)
|
||||
return text_field
|
||||
|
||||
def odoo_web_click_principal_menu(self):
|
||||
# Click menu button
|
||||
button = self.click_with_mouse_move(
|
||||
By.CSS_SELECTOR, "a.full[data-toggle='dropdown']", timeout=30
|
||||
)
|
||||
return button
|
||||
|
||||
def odoo_web_principal_menu_click_root_menu(self, from_text=""):
|
||||
if not from_text:
|
||||
raise Exception(
|
||||
"Cannot click, empty parameter from method"
|
||||
" odoo_web_principal_menu_click_root_menu"
|
||||
)
|
||||
button = self.click_with_mouse_move(
|
||||
By.LINK_TEXT, from_text, timeout=30
|
||||
)
|
||||
# If not work, force it
|
||||
# selenium_tool.driver.execute_script("arguments[0].click();", button)
|
||||
return button
|
||||
|
||||
def odoo_web_action_button_new(self):
|
||||
# From web view kanban, list
|
||||
return self.click_with_mouse_move(
|
||||
By.CLASS_NAME, "o-kanban-button-new", timeout=30
|
||||
)
|
||||
|
||||
def odoo_web_kanban_click(self, button_text, btn_class="btn-primary"):
|
||||
# From web view kanban, list
|
||||
return self.click_with_mouse_move(
|
||||
By.XPATH,
|
||||
f"//button[contains(@class, 'btn {btn_class} o_kanban_edit') and"
|
||||
f" text()='{button_text}']",
|
||||
timeout=30,
|
||||
)
|
||||
|
||||
def odoo_web_form_notebook_tab_click(self, tab_text):
|
||||
return self.click_with_mouse_move(
|
||||
By.XPATH,
|
||||
f"//a[text()='{tab_text}']",
|
||||
timeout=30,
|
||||
)
|
||||
|
||||
def odoo_fill_widget_selection(self, field_name, text):
|
||||
return self.odoo_fill_widget_many2one(field_name, text)
|
||||
|
||||
def odoo_fill_widget_boolean(self, field_name, value):
|
||||
self.driver.implicitly_wait(10)
|
||||
checkbox_div = self.driver.find_element(
|
||||
By.XPATH, f"//div[@name='{field_name}']"
|
||||
)
|
||||
checkbox = checkbox_div.find_element(
|
||||
By.CSS_SELECTOR, 'input[type="checkbox"]'
|
||||
)
|
||||
is_selected = checkbox.get_attribute("selected")
|
||||
# Check if already set
|
||||
if is_selected == "true" and value:
|
||||
return checkbox
|
||||
elif is_selected is None and not value:
|
||||
return checkbox
|
||||
parent_element = checkbox.find_element(By.XPATH, "..")
|
||||
parent_element.click()
|
||||
return checkbox
|
||||
|
||||
def odoo_fill_widget_many2one(self, field_name, text):
|
||||
# TODO read this file odoo/addons/web/static/src/js/fields/field_registry.js
|
||||
div_field = WebDriverWait(self.driver, 10).until(
|
||||
EC.presence_of_element_located((By.NAME, field_name))
|
||||
)
|
||||
|
||||
input_field = div_field.find_element(By.XPATH, ".//input")
|
||||
input_field.send_keys(text)
|
||||
# TODO improve speed by observation of comportement
|
||||
time.sleep(0.5)
|
||||
input_field.send_keys(Keys.ENTER)
|
||||
|
||||
return input_field
|
||||
|
||||
def odoo_fill_widget_date(self, field_name, date_to_select):
|
||||
# Type date
|
||||
self.driver.implicitly_wait(10)
|
||||
checkbox_div = self.driver.find_element(
|
||||
By.XPATH, f"//div[@name='{field_name}']"
|
||||
)
|
||||
checkbox_div.click()
|
||||
# TODO improve speed by observation of comportement
|
||||
time.sleep(0.5)
|
||||
checkbox_date_div = self.driver.find_element(
|
||||
By.CSS_SELECTOR, ".bootstrap-datetimepicker-widget"
|
||||
)
|
||||
# time.sleep(0.5)
|
||||
str_date_today = date_to_select.strftime("%Y-%m-%d")
|
||||
new_value = checkbox_date_div.find_element(
|
||||
By.XPATH, f"//td[@data-day='{str_date_today}']"
|
||||
)
|
||||
new_value.click()
|
||||
return new_value
|
||||
|
||||
def start_record(self):
|
||||
# Démarrer l'enregistrement
|
||||
if self.config.record_mode:
|
||||
if self.config.record_wait_before_start_time:
|
||||
time.sleep(int(self.config.record_wait_before_start_time))
|
||||
# Sync before record
|
||||
has_sync_error = False
|
||||
if self.config.sync_file_record_read:
|
||||
if not self.config.sync_file_record_write:
|
||||
print(
|
||||
"Error, cannot sync, missing 'sync_file_record_write'"
|
||||
)
|
||||
has_sync_error = True
|
||||
if self.config.sync_file_record_write:
|
||||
if not self.config.sync_file_record_read:
|
||||
print(
|
||||
"Error, cannot sync, missing 'sync_file_record_read'"
|
||||
)
|
||||
has_sync_error = True
|
||||
if (
|
||||
not has_sync_error
|
||||
and self.config.sync_file_record_read
|
||||
and self.config.sync_file_record_write
|
||||
):
|
||||
# Do sync
|
||||
file_name_1 = f"/tmp/erplibre_sync_temp_file{self.config.sync_file_record_write}"
|
||||
file_name_2 = f"/tmp/erplibre_sync_temp_file{self.config.sync_file_record_read}"
|
||||
with open(file_name_1, "w") as file:
|
||||
file.write(f"Recording {self.filename}\n")
|
||||
while not os.path.exists(file_name_2):
|
||||
var_wait_time = 0.001
|
||||
print(f"File {self.filename} wait {var_wait_time} seconds")
|
||||
time.sleep(var_wait_time)
|
||||
self.video_recorder.start()
|
||||
|
||||
def stop_record(self):
|
||||
|
|
@ -377,6 +764,7 @@ class SeleniumLib(object):
|
|||
time.sleep(self.config.selenium_video_time_waiting_end)
|
||||
self.video_recorder.stop()
|
||||
print("End of recording video")
|
||||
print(self.filename)
|
||||
|
||||
if self.config.selenium_video_auto_play_video:
|
||||
print(f"Play video {self.filename}")
|
||||
|
|
@ -402,7 +790,7 @@ def fill_parser(parser):
|
|||
"--selenium_default_delay",
|
||||
default=0.4,
|
||||
type=float,
|
||||
help="Pause at the end before close video.",
|
||||
help="Pause at the end of an action.",
|
||||
)
|
||||
|
||||
group_browser = parser.add_argument_group(title="Browser")
|
||||
|
|
@ -434,6 +822,31 @@ def fill_parser(parser):
|
|||
action="store_true",
|
||||
help="Start recording (not finish to be implemented).",
|
||||
)
|
||||
group_record.add_argument(
|
||||
"--record_wait_before_start_time",
|
||||
help="Time to wait in second before start recording.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--video_suffix",
|
||||
default="",
|
||||
help="Will modify video name.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--sync_file_record_read",
|
||||
default="",
|
||||
help=(
|
||||
"Will sync and check file from tmp before record, write before"
|
||||
" read."
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--sync_file_record_write",
|
||||
default="",
|
||||
help=(
|
||||
"Will sync and check file from tmp before record, write before"
|
||||
" read."
|
||||
),
|
||||
)
|
||||
group_record.add_argument(
|
||||
"--selenium_video_time_waiting_end",
|
||||
default=5,
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class VideoRecorder(object):
|
|||
self,
|
||||
driver,
|
||||
filename="video.webm",
|
||||
framerate="25/1",
|
||||
framerate="33/1",
|
||||
width=None,
|
||||
height=None,
|
||||
):
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import sys
|
|||
import time
|
||||
|
||||
import selenium_lib
|
||||
|
||||
from selenium.webdriver.common.by import By
|
||||
|
||||
|
||||
|
|
@ -35,18 +34,24 @@ def run(config, selenium_tool):
|
|||
# Trouvez les éléments du formulaire
|
||||
courriel_input = selenium_tool.driver.find_element(By.NAME, "login")
|
||||
mot_de_passe_input = selenium_tool.driver.find_element(By.NAME, "password")
|
||||
try:
|
||||
connexion_button = selenium_tool.driver.find_element(
|
||||
By.XPATH,
|
||||
"/html/body/div/div/div/form/div[3]/button",
|
||||
# '//button[contains(text(), "Log in")]'
|
||||
)
|
||||
except Exception:
|
||||
connexion_button = selenium_tool.driver.find_element(
|
||||
By.XPATH,
|
||||
"/html/body/div/main/div/form/div[3]/button",
|
||||
# '//button[contains(text(), "Connexion")]'
|
||||
)
|
||||
div_connexion_button = selenium_tool.driver.find_element(
|
||||
By.CLASS_NAME, "oe_login_buttons"
|
||||
)
|
||||
connexion_button = div_connexion_button.find_element(
|
||||
By.CLASS_NAME, "btn-primary"
|
||||
)
|
||||
# try:
|
||||
# connexion_button = selenium_tool.driver.find_element(
|
||||
# By.XPATH,
|
||||
# "/html/body/div/div/div/form/div[3]/button",
|
||||
# # '//button[contains(text(), "Log in")]'
|
||||
# )
|
||||
# except Exception:
|
||||
# connexion_button = selenium_tool.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(config.default_email_auth)
|
||||
|
|
@ -105,6 +110,7 @@ def run(config, selenium_tool):
|
|||
if config.open_dashboard:
|
||||
selenium_tool.click(
|
||||
"/html/body/header/nav/div/div[1]/div[2]/div/div/div/ul/li[3]/a",
|
||||
timeout=15,
|
||||
)
|
||||
|
||||
# Open conversation chat
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@
|
|||
|
||||
# This script need only basic importation
|
||||
import argparse
|
||||
import logging
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO"))
|
||||
|
||||
|
|
@ -100,6 +100,11 @@ def get_config():
|
|||
action="store_true",
|
||||
help="Install developer environment.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--partial_install",
|
||||
action="store_true",
|
||||
help="Preparation environment file, without installation. Docker need this",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--force_install",
|
||||
action="store_true",
|
||||
|
|
@ -457,7 +462,15 @@ class Update:
|
|||
|
||||
# Force create addons link
|
||||
if os.path.isdir(ADDONS_PATH):
|
||||
os.remove(ADDONS_PATH)
|
||||
if os.path.islink(ADDONS_PATH):
|
||||
os.remove(ADDONS_PATH)
|
||||
else:
|
||||
os.rename(
|
||||
ADDONS_PATH,
|
||||
ADDONS_PATH
|
||||
+ "_"
|
||||
+ time.strftime('%Yy%mm%dd-%Hh%Mm%Ss'),
|
||||
)
|
||||
os.symlink(addons_path_with_version, ADDONS_PATH)
|
||||
return status
|
||||
|
||||
|
|
@ -688,13 +701,14 @@ def main():
|
|||
|
||||
_logger.info("Validate environment")
|
||||
status = 0
|
||||
if update.config.install_dev or update.config.is_in_switch:
|
||||
if update.config.install_dev or update.config.partial_install or update.config.is_in_switch:
|
||||
status = update.validate_environment()
|
||||
if update.config.install:
|
||||
status = update.install_system()
|
||||
if (
|
||||
update.config.force_install
|
||||
or update.config.install_dev
|
||||
or update.config.partial_install
|
||||
or update.config.is_in_switch
|
||||
) and not status:
|
||||
update.update_environment()
|
||||
|
|
|
|||
2
test.sh
2
test.sh
|
|
@ -14,7 +14,7 @@ if [ ! -f "${CONFIG_PATH}" ]; then
|
|||
fi
|
||||
fi
|
||||
|
||||
coverage run -p ./odoo/odoo-bin -c "${CONFIG_PATH}" --limit-time-real 99999 --limit-time-cpu 99999 --log-level=test --test-enable --stop-after-init "$@"
|
||||
coverage run -p ./odoo/odoo-bin -c "${CONFIG_PATH}" --limit-time-real 99999 --limit-time-cpu 99999 --log-level=test --test-enable --no-http --stop-after-init "$@"
|
||||
retVal=$?
|
||||
if [[ $retVal -ne 0 ]]; then
|
||||
echo "${Red}Error${Color_Off} run.sh"
|
||||
|
|
|
|||
Loading…
Reference in a new issue