Merge branch 'develop'

- Support ubuntu 23.10
- Script search docker compose
- Improve run_parallel_test
- Update poetry 1.3.1 to 1.5.1
- Update changelog
- Support old docker compose with new syntax
This commit is contained in:
Mathieu Benoit 2024-05-03 23:20:56 -04:00
commit d7f6c257d2
64 changed files with 1450 additions and 1307 deletions

View file

@ -11,6 +11,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
- Selenium script to increase open software client interface and automated some actions. - Selenium script to increase open software client interface and automated some actions.
- FAQ about kill git-daemon - FAQ about kill git-daemon
- Support Ubuntu 23.10
## Changed ## Changed
@ -19,6 +20,11 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
- Improve format script to help code-generator - Improve format script to help code-generator
- Improve PyCharm script - Improve PyCharm script
- Support OSX for open-terminal - Support OSX for open-terminal
- Remove docker-compose and replace by docker compose
- Update Poetry 1.3.1 to 1.5.1
- Test can be launched with a json configuration and support log/result individually
- Script to search docker compose into the system
- Script search class model can output into json format and support field information
### Fixed ### Fixed

View file

@ -935,15 +935,15 @@ clean_test:
# run docker # run docker
.PHONY: docker_run .PHONY: docker_run
docker_run: docker_run:
docker-compose up docker compose up
.PHONY: docker_run_daemon .PHONY: docker_run_daemon
docker_run_daemon: docker_run_daemon:
docker-compose up -d docker compose up -d
.PHONY: docker_stop .PHONY: docker_stop
docker_stop: docker_stop:
docker-compose down docker compose down
.PHONY: docker_restart_daemon .PHONY: docker_restart_daemon
docker_restart_daemon: docker_restart_daemon:
@ -956,11 +956,11 @@ docker_show_databases:
.PHONY: docker_show_logs_live .PHONY: docker_show_logs_live
docker_show_logs_live: docker_show_logs_live:
docker-compose logs -f docker compose logs -f
.PHONY: docker_show_process .PHONY: docker_show_process
docker_show_process: docker_show_process:
docker-compose ps docker compose ps
.PHONY: docker_exec_erplibre .PHONY: docker_exec_erplibre
docker_exec_erplibre: docker_exec_erplibre:

View file

@ -17,8 +17,7 @@ make install
``` ```
Update your configuration if you need to run from another interface than 127.0.0.1, file `config.conf` Update your configuration if you need to run from another interface than 127.0.0.1, file `config.conf`
``` ```
#xmlrpc_interface = 127.0.0.1 xmlrpc_interface = 0.0.0.0
#netrpc_interface = 127.0.0.1
``` ```
Ready to execute: Ready to execute:
```bash ```bash
@ -31,7 +30,7 @@ First, install dependencies to run docker, check script `./script/install/instal
The docker volume is bound to the directory name, therefore create a unique directory name and run: The docker volume is bound to the directory name, therefore create a unique directory name and run:
```bash ```bash
wget https://raw.githubusercontent.com/ERPLibre/ERPLibre/v1.5.0/docker-compose.yml wget https://raw.githubusercontent.com/ERPLibre/ERPLibre/v1.5.0/docker-compose.yml
docker-compose up -d docker compose up -d
``` ```
For more information, read [Docker guide](./docker/README.md). For more information, read [Docker guide](./docker/README.md).

View file

@ -1,19 +1,21 @@
#!/usr/bin/env bash #!/usr/bin/env bash
source ./.venv/bin/activate source ./.venv/bin/activate
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
CONFIG_PATH="./config.conf" CONFIG_PATH="./config.conf"
ORIGIN_CONFIG_PATH=CONFIG_PATH ORIGIN_CONFIG_PATH=CONFIG_PATH
if [ ! -f "${CONFIG_PATH}" ]; then if [ ! -f "${CONFIG_PATH}" ]; then
CONFIG_PATH="/etc/odoo/odoo.conf" CONFIG_PATH="/etc/odoo/odoo.conf"
if [ ! -f "${CONFIG_PATH}" ]; then if [ ! -f "${CONFIG_PATH}" ]; then
echo "Cannot find ERPLibre configuration ${ORIGIN_CONFIG_PATH}, did you install ERPLibre? > make install" echo "${Red}Cannot find${Color_Off} ERPLibre configuration ${ORIGIN_CONFIG_PATH}, did you install ERPLibre? > make install"
exit 1 exit 1
fi fi
fi fi
coverage run -p ./odoo/odoo-bin -c ${CONFIG_PATH} --limit-time-real 99999 --limit-time-cpu 99999 $@ coverage run -p ./odoo/odoo-bin -c "${CONFIG_PATH}" --limit-time-real 99999 --limit-time-cpu 99999 "$@"
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error coverage_run.sh" echo "${Red}Error${Color_Off} run.sh"
exit 1 exit 1
fi fi

View file

@ -148,3 +148,22 @@ Add line at the end of config.conf
``` ```
limit_memory_hard = 0 limit_memory_hard = 0
``` ```
### Docker - All interface bind docker
Create a subnet
```bash
sudo docker network create localnetwork --subnet 10.0.1.0/24
```
And create `docker-compose.override.yml` at root project with
```yaml
version: '3'
networks:
default:
external:
name: localnetwork
```

View file

@ -74,9 +74,8 @@ sudo systemctl -feu [EL_USER]
Comment the following line in `/[EL_USER]/erplibre/config.conf` Comment the following line in `/[EL_USER]/erplibre/config.conf`
``` ```
#xmlrpc_interface = 127.0.0.1 xmlrpc_interface = 0.0.0.0
#netrpc_interface = 127.0.0.1 proxy_mode = True
#proxy_mode = True
``` ```
Add your address ip server_name in nginx config `/etc/nginx/sites-available/[EL_WEBSITE_NAME]` Add your address ip server_name in nginx config `/etc/nginx/sites-available/[EL_WEBSITE_NAME]`
@ -183,8 +182,8 @@ Note, the goal is to call `env['ir.module.module'].update_list()`.
Restart the docker : Restart the docker :
```bash ```bash
docker-compose down docker compose down
docker-compose up -d docker compose up -d
``` ```
Revert the command in docker-compose.yml. Revert the command in docker-compose.yml.
@ -192,7 +191,7 @@ Revert the command in docker-compose.yml.
You can validate in log the update, you need to find `odoo.modules.loading: updating modules list`, check You can validate in log the update, you need to find `odoo.modules.loading: updating modules list`, check
```bash ```bash
docker-compose logs -f docker compose logs -f
``` ```
## Update all ## Update all

View file

@ -38,15 +38,15 @@ docker build -f Dockerfile.prod.pkg -t technolibre/erplibre:12.0-pkg .
Go at the root of this git project. Go at the root of this git project.
```bash ```bash
cd ERPLibre cd ERPLibre
docker-compose -f docker-compose.yml up -d docker compose -f docker-compose.yml up -d
``` ```
### Diagnostic Docker-Compose ### Diagnostic Docker-Compose
Show docker-compose information Show docker-compose information
```bash ```bash
docker-compose ps docker compose ps
docker-compose logs IMAGE_NAME docker compose logs IMAGE_NAME
``` ```
Show docker information Show docker information
@ -90,7 +90,7 @@ docker rmi $(docker images -q)
Delete volumes Delete volumes
```bash ```bash
docker-compose rm -v docker compose rm -v
``` ```
Delete containers Delete containers

View file

@ -38,7 +38,7 @@ then
elif [[ "$ENV" == "dev" ]] && [ -z ${CURRENT_UID} ] elif [[ "$ENV" == "dev" ]] && [ -z ${CURRENT_UID} ]
then then
echo 'Please run as follows : CURRENT_UID=$(id -u):$(id -g) docker-compose up' echo 'Please run as follows : CURRENT_UID=$(id -u):$(id -g) docker compose up'
exit 1 exit 1
fi fi

1060
poetry.lock generated

File diff suppressed because it is too large Load diff

View file

@ -19,49 +19,49 @@ authors = [ "Mathieu Benoit <mathben@technolibre.ca>",]
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "^3.7.16" python = "^3.7.16"
acme = "^2.6.0" acme = "2.6.0"
agithub = "^2.2.2" agithub = "^2.2.2"
aioshutil = "<1.2" aioshutil = "<1.2"
altair = "^5.0.1" altair = "5.0.1"
argcomplete = "^3.1.1" argcomplete = "3.1.1"
asterisk = "^0.0.8" asterisk = "^0.0.8"
astor = "^0.8.1" astor = "^0.8.1"
azure-identity = "^1.13.0" azure-identity = "^1.15.0"
azure-storage-blob = "^12.16.0" azure-storage-blob = "^12.19.0"
babel = "2.9.1" babel = "2.9.1"
beautifulsoup4 = "^4.12.2" beautifulsoup4 = "^4.12.2"
bokeh = "1.1.0" bokeh = "1.1.0"
boto3 = ">=1.20.41" boto3 = ">=1.20.41"
cachetools = ">=2.0.1" cachetools = ">=2.0.1"
cerberus = "^1.3.4" cerberus = "^1.3.5"
chardet = "5.0.0" chardet = "5.0.0"
click = "^8.1.4" click = "^8.1.7"
cloudflare = "^2.11.6" cloudflare = "^2.14.3"
code-writer = "^1.1.1" code-writer = "^1.1.1"
colorama = "^0.4.6" colorama = "^0.4.6"
configparser = "5.0.2" configparser = "5.0.2"
coverage = "^7.2.7" coverage = "7.2.7"
cryptography = "39.0.1" cryptography = "39.0.1"
css-html-prettify = "^2.5.5" css-html-prettify = "^2.5.5"
cython = "^0.29.36" cython = "^3.0.6"
ddt = "1.2.0" ddt = "1.2.0"
decorator = "4.0.10" decorator = "4.0.10"
dnspython = "^2.3.0" dnspython = "2.3.0"
docutils = "0.17.1" docutils = "0.17.1"
ebaysdk = "2.1.5" ebaysdk = "2.1.5"
email-validator = "^2.0.0.post2" email-validator = "2.1.0"
emoji = "^2.6.0" emoji = "^2.9.0"
extract-msg = "<0.30" extract-msg = "0.36.1"
factur-x = "^2.5" factur-x = "^3.1"
feedparser = "6.0.10" feedparser = "6.0.10"
flake8 = "<6.0.0" flake8 = "<6.0.0"
formio-data = "^0.5.1" formio-data = "^1.2.4"
freezegun = "1.2.2" freezegun = "1.2.2"
future = "0.18.3" future = "0.18.3"
geojson = "<3.0.0" geojson = "<3.0.0"
gevent = "1.5.0" gevent = "1.5.0"
gitpython = "3.1.30" gitpython = "3.1.30"
giturlparse = "^0.10.0" giturlparse = "0.10.0"
greenlet = "0.4.14" greenlet = "0.4.14"
html2text = "2016.9.19" html2text = "2016.9.19"
invoice2data = "0.3.5" invoice2data = "0.3.5"
@ -70,7 +70,7 @@ isort = "<5.12.0"
jinja2 = "2.11.3" jinja2 = "2.11.3"
jira = "2.0.0" jira = "2.0.0"
jose = "^1.0.0" jose = "^1.0.0"
josepy = "^1.13.0" josepy = "^1.14.0"
js2py = "^0.74" js2py = "^0.74"
keystoneauth1 = "3.14.0" keystoneauth1 = "3.14.0"
lasso = "^0.1.0" lasso = "^0.1.0"
@ -78,7 +78,7 @@ libsass = "0.12.3"
lxml = "4.9.1" lxml = "4.9.1"
mako = "1.2.2" mako = "1.2.2"
markupsafe = "0.23" markupsafe = "0.23"
mmg = "^1.0.3" mmg = "1.0.3"
mock = "2.0.0" mock = "2.0.0"
mpld3 = "^0.5.9" mpld3 = "^0.5.9"
mysqlclient = "2.1.1" mysqlclient = "2.1.1"
@ -86,20 +86,20 @@ num2words = "0.5.6"
numpy = "1.21.1" numpy = "1.21.1"
oauthlib = "2.1.0" oauthlib = "2.1.0"
oca-decorators = "^0.0.1" oca-decorators = "^0.0.1"
odoorpc = "^0.9.0" odoorpc = "^0.10.1"
ofxparse = "0.16" ofxparse = "0.16"
openpyxl = "^3.1.2" openpyxl = "^3.1.2"
openupgradelib = "^3.4.1" openupgradelib = "^3.5.0"
orjson = "3.6.0" orjson = "3.6.0"
ovh = "^1.1.0" ovh = "^1.1.0"
paho-mqtt = "^1.6.1" paho-mqtt = "^1.6.1"
pandas = "1.3.5" pandas = "1.3.5"
paramiko = "^3.2.0" paramiko = "^3.3.1"
passlib = "1.6.5" passlib = "1.6.5"
pdf2image = "^1.16.3" pdf2image = "^1.16.3"
pdfminer = "^20191125" pdfminer = "^20191125"
pexpect = "^4.8.0" pexpect = "^4.9.0"
phonenumbers = "^8.13.15" phonenumbers = "^8.13.26"
pillow = "9.3.0" pillow = "9.3.0"
plotly = "4.1.0" plotly = "4.1.0"
portalocker = "1.7.1" portalocker = "1.7.1"
@ -110,7 +110,7 @@ psycopg2 = "2.9.5"
py-asterisk = "^0.5.18" py-asterisk = "^0.5.18"
py3o-formats = "^0.3" py3o-formats = "^0.3"
py3o-template = "^0.10.0" py3o-template = "^0.10.0"
pycountry = "^22.3.5" pycountry = "22.3.5"
pydot = "1.2.3" pydot = "1.2.3"
pygments = "2.7.4" pygments = "2.7.4"
pygments-csv-lexer = ">=0.1,<1.0" pygments-csv-lexer = ">=0.1,<1.0"
@ -118,9 +118,9 @@ pygount = ">1.2.1"
pyjsparser = "^2.7.1" pyjsparser = "^2.7.1"
pyjwt = "2.5.0" pyjwt = "2.5.0"
pyldap = "2.4.28" pyldap = "2.4.28"
pymssql = "^2.2.7" pymssql = "^2.2.11"
pymysql = "^1.1.0" pymysql = "^1.1.0"
pyotp = "^2.8.0" pyotp = "^2.9.0"
pyparsing = "2.1.10" pyparsing = "2.1.10"
pypdf2 = "1.27.9" pypdf2 = "1.27.9"
pyproj = "3.2.1" pyproj = "3.2.1"
@ -133,9 +133,9 @@ python-git = "^2018.2.1"
python-jose = "^3.3.0" python-jose = "^3.3.0"
python-json-logger = "0.1.5" python-json-logger = "0.1.5"
python-keystoneclient = "3.22.0" python-keystoneclient = "3.22.0"
python-ldap = "^3.4.3" python-ldap = "^3.4.4"
python-slugify = ">=3.0.2" python-slugify = ">=3.0.2"
python-stdnum = "^1.18" python-stdnum = "^1.19"
python-swiftclient = "3.9.0" python-swiftclient = "3.9.0"
python-u2flib-server = "^5.0.1" python-u2flib-server = "^5.0.1"
pytz = ">=2022.7" pytz = ">=2022.7"
@ -149,9 +149,9 @@ requests = "2.28.1"
requests-mock = "^1.11.0" requests-mock = "^1.11.0"
requests-oauthlib = "1.1.0" requests-oauthlib = "1.1.0"
requests-toolbelt = "0.9.1" requests-toolbelt = "0.9.1"
responses = "^0.23.1" responses = "0.23.1"
retrying = "^1.3.4" retrying = "^1.3.4"
sentry-sdk = "^1.27.1" sentry-sdk = "^1.39.1"
serial = "^0.0.97" serial = "^0.0.97"
setuptools = "65.5.1" setuptools = "65.5.1"
shapely = "1.8.5" shapely = "1.8.5"
@ -160,26 +160,26 @@ slugify = "^0.0.1"
soappy = "^0.12.22" soappy = "^0.12.22"
sphinx = "3.0" sphinx = "3.0"
sphinx-intl = "^2.1.0" sphinx-intl = "^2.1.0"
sphinx-rtd-theme = "^1.2.2" sphinx-rtd-theme = "1.2.2"
sqlalchemy = "^2.0.18" sqlalchemy = "^2.0.23"
sqlparse = "^0.4.4" sqlparse = "^0.4.4"
statsd = "3.2.1" statsd = "3.2.1"
toml = "^0.10.2" toml = "^0.10.2"
tornado = "6.1" tornado = "6.1"
tqdm = "^4.65.0" tqdm = "^4.66.1"
unidecode = "1.0.22" unidecode = "1.0.22"
unidiff = "^0.7.5" unidiff = "^0.7.5"
urllib3 = ">=1.26.13" urllib3 = ">=1.26.13"
uvloop = "^0.17.0" uvloop = "0.17.0"
vcrpy = ">=2.1.1" vcrpy = ">=2.1.1"
vcrpy-unittest = "^0.1.7" vcrpy-unittest = "^0.1.7"
vobject = "0.9.3" vobject = "0.9.3"
voicent-python = "^1.0" voicent-python = "^1.0"
webcolors = "^1.13" webcolors = "^1.13"
websocket-client = "^1.6.1" websocket-client = "1.6.1"
werkzeug = "0.16.1" werkzeug = "0.16.1"
wget = "^3.2" wget = "^3.2"
wheel = "^0.40.0" wheel = "^0.42.0"
win-unicode-console = "^0.5" win-unicode-console = "^0.5"
xlrd = "1.0.0" xlrd = "1.0.0"
xlsxwriter = "0.9.3" xlsxwriter = "0.9.3"

View file

@ -92,6 +92,25 @@ win_unicode_console
# Security issue, depend on extract-msg 0.36.1 # Security issue, depend on extract-msg 0.36.1
chardet==5.0.0 chardet==5.0.0
extract-msg==0.36.1 extract-msg==0.36.1
extract_msg==0.36.1
# Limitation because python3.7
argcomplete==3.1.1
responses==0.23.1
dnspython==2.3.0
acme==2.6.0
altair==5.0.1
pycountry==22.3.5
email-validator==2.1.0
email_validator==2.1.0
sphinx-rtd-theme==1.2.2
sphinx_rtd_theme==1.2.2
uvloop==0.17.0
coverage==7.2.7
websocket-client==1.6.1
websocket_client==1.6.1
mmg==1.0.3
giturlparse==0.10.0
# Force version for security update # Force version for security update
pyyaml==6.0 pyyaml==6.0

8
run.sh
View file

@ -1,22 +1,24 @@
#!/usr/bin/env bash #!/usr/bin/env bash
source ./.venv/bin/activate source ./.venv/bin/activate
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
CONFIG_PATH="./config.conf" CONFIG_PATH="./config.conf"
ORIGIN_CONFIG_PATH=CONFIG_PATH ORIGIN_CONFIG_PATH=CONFIG_PATH
if [ ! -f "${CONFIG_PATH}" ]; then if [ ! -f "${CONFIG_PATH}" ]; then
CONFIG_PATH="/etc/odoo/odoo.conf" CONFIG_PATH="/etc/odoo/odoo.conf"
if [ ! -f "${CONFIG_PATH}" ]; then if [ ! -f "${CONFIG_PATH}" ]; then
echo "Cannot find ERPLibre configuration ${ORIGIN_CONFIG_PATH}, did you install ERPLibre? > make install" echo "${Red}Cannot find${Color_Off} ERPLibre configuration ${ORIGIN_CONFIG_PATH}, did you install ERPLibre? > make install"
exit 1 exit 1
fi fi
fi fi
python3 ./odoo/odoo-bin -c ${CONFIG_PATH} --limit-time-real 99999 --limit-time-cpu 99999 --limit-memory-hard=0 "$@" python3 ./odoo/odoo-bin -c "${CONFIG_PATH}" --limit-time-real 99999 --limit-time-cpu 99999 --limit-memory-hard=0 "$@"
# When need more memory RAM for instance by force # When need more memory RAM for instance by force
#python3 ./odoo/odoo-bin -c ${CONFIG_PATH} --limit-time-real 99999 --limit-time-cpu 99999 --limit-memory-soft=8589934592 --limit-memory-hard=10737418240 $@ #python3 ./odoo/odoo-bin -c ${CONFIG_PATH} --limit-time-real 99999 --limit-time-cpu 99999 --limit-memory-soft=8589934592 --limit-memory-hard=10737418240 $@
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error run.sh" echo "${Red}Error${Color_Off} run.sh"
exit 1 exit 1
fi fi

View file

@ -22,6 +22,7 @@ def get_config():
formatter_class=argparse.RawDescriptionHelpFormatter, formatter_class=argparse.RawDescriptionHelpFormatter,
description="""\ description="""\
Check if module exist and is not multiple here to manage conflict. Check if module exist and is not multiple here to manage conflict.
Return 0 if success, return 1 if missing module, return 2 if multiple same module
""", """,
epilog="""\ epilog="""\
""", """,
@ -43,6 +44,11 @@ def get_config():
action="store_true", action="store_true",
help="Enable debug output", help="Enable debug output",
) )
parser.add_argument(
"--output_path",
action="store_true",
help="Print path if module exist",
)
args = parser.parse_args() args = parser.parse_args()
return args return args
@ -88,8 +94,10 @@ def main():
lst_module_not_exist.append(module) lst_module_not_exist.append(module)
is_good = True is_good = True
error_missing_module = False
if lst_module_not_exist: if lst_module_not_exist:
is_good = False is_good = False
error_missing_module = True
module_list = "'" + "', '".join(lst_module_not_exist) + "'" module_list = "'" + "', '".join(lst_module_not_exist) + "'"
_logger.error( _logger.error(
"Missing" "Missing"
@ -97,14 +105,19 @@ def main():
) )
if dct_module_exist: if dct_module_exist:
for key, lst_value in dct_module_exist.items(): for key, lst_value in dct_module_exist.items():
is_print_value = False
if len(lst_value) != 1: if len(lst_value) != 1:
is_print_value = True
is_good = False is_good = False
module_list = "'" + "', '".join(lst_value) + "'" module_list = "'" + "', '".join(lst_value) + "'"
_logger.error(f"Conflict modules: {module_list}") _logger.error(f"Conflict modules: {module_list}")
elif lst_value and config.output_path:
is_print_value = True
if is_print_value:
for value in lst_value: for value in lst_value:
print(value) print(value)
if dct_module_exist_empty: if dct_module_exist_empty and not config.output_path:
for key, lst_value in dct_module_exist_empty.items(): for key, lst_value in dct_module_exist_empty.items():
module_list = "'" + "', '".join(lst_value) + "'" module_list = "'" + "', '".join(lst_value) + "'"
_logger.warning( _logger.warning(
@ -112,7 +125,11 @@ def main():
f" {module_list}" f" {module_list}"
) )
return 0 if is_good else -1 if not is_good:
if error_missing_module:
return 1
return 2
return 0
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -1,4 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
# Argument 3 is config # Argument 3 is config
if [[ $# -eq 3 ]]; then if [[ $# -eq 3 ]]; then
./script/addons/check_addons_exist.py -m "$2" -c "$3" ./script/addons/check_addons_exist.py -m "$2" -c "$3"
@ -7,7 +10,7 @@ else
fi fi
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error check_addons_exist.py into coverage_install_addons.sh" echo -e "${Red}Error${Color_Off} check_addons_exist.py into coverage_install_addons.sh"
exit 1 exit 1
fi fi
@ -21,6 +24,6 @@ fi
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error coverage_run.sh into coverage_install_addons.sh" echo -e "${Red}Error${Color_Off} coverage_run.sh into coverage_install_addons.sh"
exit 1 exit 1
fi fi

View file

@ -1,4 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
# Argument 3 is config # Argument 3 is config
if [[ $# -eq 3 ]]; then if [[ $# -eq 3 ]]; then
./script/addons/check_addons_exist.py -m "$2" -c "$3" ./script/addons/check_addons_exist.py -m "$2" -c "$3"
@ -7,7 +10,7 @@ else
fi fi
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error check_addons_exist.py into coverage_install_addons_dev.sh" echo -e "${Red}Error${Color_Off} check_addons_exist.py into coverage_install_addons_dev.sh"
exit 1 exit 1
fi fi
@ -21,6 +24,6 @@ fi
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error coverage_run.sh into coverage_install_addons_dev.sh" echo -e "${Red}Error${Color_Off} coverage_run.sh into coverage_install_addons_dev.sh"
exit 1 exit 1
fi fi

View file

@ -1,15 +1,18 @@
#!/usr/bin/env bash #!/usr/bin/env bash
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
# "$1" code_generator_name # "$1" code_generator_name
./script/database/db_restore.py --database "$1" ./script/database/db_restore.py --database "$1"
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error ./script/database/db_restore.py into coverage_install_addons_restore_dev.sh" echo -e "${Red}Error${Color_Off} ./script/database/db_restore.py into coverage_install_addons_restore_dev.sh"
exit 1 exit 1
fi fi
./script/addons/coverage_install_addons_dev.sh "$1" "$1" ./script/addons/coverage_install_addons_dev.sh "$1" "$1"
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error ./script/addons/coverage_install_addons_dev.sh into coverage_install_addons_restore_dev.sh" echo -e "${Red}Error${Color_Off} ./script/addons/coverage_install_addons_dev.sh into coverage_install_addons_restore_dev.sh"
exit 1 exit 1
fi fi

View file

@ -1,4 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
# Argument 3 is config # Argument 3 is config
if [[ $# -eq 3 ]]; then if [[ $# -eq 3 ]]; then
./script/addons/check_addons_exist.py -m "$2" -c "$3" ./script/addons/check_addons_exist.py -m "$2" -c "$3"
@ -7,7 +10,7 @@ else
fi fi
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error check_addons_exist.py into install_addons.sh" echo -e "${Red}Error${Color_Off} check_addons_exist.py into install_addons.sh"
exit 1 exit 1
fi fi
@ -21,6 +24,6 @@ fi
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error run.sh into install_addons.sh" echo -e "${Red}Error${Color_Off} run.sh into install_addons.sh"
exit 1 exit 1
fi fi

View file

@ -1,21 +1,24 @@
#!/usr/bin/env bash #!/usr/bin/env bash
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
# "$1" module_name # "$1" module_name
# "$1" code_generator_template_name # "$1" code_generator_template_name
./script/database/db_restore.py --database "$2" ./script/database/db_restore.py --database "$2"
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error ./script/database/db_restore.py into install_addons_cg_template_restore_dev.sh" echo -e "${Red}Error${Color_Off} ./script/database/db_restore.py into install_addons_cg_template_restore_dev.sh"
exit 1 exit 1
fi fi
./script/addons/install_addons_dev.sh "$2" "$1" ./script/addons/install_addons_dev.sh "$2" "$1"
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error ./script/addons/install_addons_dev.sh install module into install_addons_cg_template_restore_dev.sh" echo -e "${Red}Error${Color_Off} ./script/addons/install_addons_dev.sh install module into install_addons_cg_template_restore_dev.sh"
exit 1 exit 1
fi fi
./script/addons/install_addons_dev.sh "$2" "$2" ./script/addons/install_addons_dev.sh "$2" "$2"
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error ./script/addons/install_addons_dev.sh install template into install_addons_cg_template_restore_dev.sh" echo -e "${Red}Error${Color_Off} ./script/addons/install_addons_dev.sh install template into install_addons_cg_template_restore_dev.sh"
exit 1 exit 1
fi fi

View file

@ -1,4 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
# Argument 3 is config # Argument 3 is config
if [[ $# -eq 3 ]]; then if [[ $# -eq 3 ]]; then
./script/addons/check_addons_exist.py -m "$2" -c "$3" ./script/addons/check_addons_exist.py -m "$2" -c "$3"
@ -7,7 +10,7 @@ else
fi fi
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error check_addons_exist.py into install_addons_dev.sh" echo -e "${Red}Error${Color_Off} check_addons_exist.py into install_addons_dev.sh"
exit 1 exit 1
fi fi
@ -22,6 +25,6 @@ fi
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error run.sh into install_addons_dev.sh" echo -e "${Red}Error${Color_Off} run.sh into install_addons_dev.sh"
exit 1 exit 1
fi fi

View file

@ -1,9 +1,12 @@
#!/usr/bin/env bash #!/usr/bin/env bash
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
# $1 BD NAME # $1 BD NAME
# $2 file_path # $2 file_path
./script/addons/install_addons.sh "$1" "$(<$2)" ./script/addons/install_addons.sh "$1" "$(<$2)"
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error ./script/addons/install_addons.sh into install_addons_from_file.sh" echo -e "${Red}Error${Color_Off} ./script/addons/install_addons.sh into install_addons_from_file.sh"
exit 1 exit 1
fi fi

View file

@ -1,15 +1,18 @@
#!/usr/bin/env bash #!/usr/bin/env bash
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
# "$1" code_generator_name # "$1" code_generator_name
./script/database/db_restore.py --database "$1" ./script/database/db_restore.py --database "$1"
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error ./script/database/db_restore.py into install_addons_restore_dev.sh" echo -e "${Red}Error${Color_Off} ./script/database/db_restore.py into install_addons_restore_dev.sh"
exit 1 exit 1
fi fi
./script/addons/install_addons_dev.sh "$1" "$1" ./script/addons/install_addons_dev.sh "$1" "$1"
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error ./script/addons/install_addons_dev.sh into install_addons_restore_dev.sh" echo -e "${Red}Error${Color_Off} ./script/addons/install_addons_dev.sh into install_addons_restore_dev.sh"
exit 1 exit 1
fi fi

View file

@ -1,5 +1,8 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# TODO addons website need to be install before to install the theme # TODO addons website need to be install before to install the theme
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
# Argument 3 is config # Argument 3 is config
if [[ $# -eq 3 ]]; then if [[ $# -eq 3 ]]; then
./script/addons/check_addons_exist.py -m "$2" -c "$3" ./script/addons/check_addons_exist.py -m "$2" -c "$3"
@ -8,7 +11,7 @@ else
fi fi
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error check_addons_exist.py into install_addons.sh" echo -e "${Red}Error${Color_Off} check_addons_exist.py into install_addons.sh"
exit 1 exit 1
fi fi
@ -22,6 +25,6 @@ fi
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error run.sh into install_addons_theme.sh" echo -e "${Red}Error${Color_Off} run.sh into install_addons_theme.sh"
exit 1 exit 1
fi fi

View file

@ -1,4 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
# Argument 3 is config # Argument 3 is config
if [[ $# -eq 3 ]]; then if [[ $# -eq 3 ]]; then
./script/addons/check_addons_exist.py -m "$2" -c "$3" ./script/addons/check_addons_exist.py -m "$2" -c "$3"
@ -7,7 +10,7 @@ else
fi fi
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error check_addons_exist.py into reinstall_addons_dev.sh" echo -e "${Red}Error${Color_Off} check_addons_exist.py into reinstall_addons_dev.sh"
exit 1 exit 1
fi fi
@ -28,6 +31,6 @@ else
fi fi
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error install_addons_dev.sh into reinstall_addons.sh" echo -e "${Red}Error${Color_Off} install_addons_dev.sh into reinstall_addons.sh"
exit 1 exit 1
fi fi

View file

@ -1,4 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
# Argument 3 is config # Argument 3 is config
if [[ $# -eq 3 ]]; then if [[ $# -eq 3 ]]; then
./script/addons/check_addons_exist.py -m "$2" -c "$3" ./script/addons/check_addons_exist.py -m "$2" -c "$3"
@ -7,7 +10,7 @@ else
fi fi
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error check_addons_exist.py into uninstall_addons.sh" echo -e "${Red}Error${Color_Off} check_addons_exist.py into uninstall_addons.sh"
exit 1 exit 1
fi fi

View file

@ -1,4 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env bash
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
echo "Update all on BD '$1'" echo "Update all on BD '$1'"
@ -6,6 +8,6 @@ echo "Update all on BD '$1'"
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error run.sh into update_addons_all.sh" echo -e "${Red}Error${Color_Off} run.sh into update_addons_all.sh"
exit 1 exit 1
fi fi

View file

@ -1,4 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
# This script will remove mail configuration, remove backup configuration, and force admin user to test/test # This script will remove mail configuration, remove backup configuration, and force admin user to test/test
echo "Update prod to dev on BD '$1'" echo "Update prod to dev on BD '$1'"
@ -6,6 +9,6 @@ echo "Update prod to dev on BD '$1'"
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error install_addons.sh into update_prod_to_dev.sh" echo -e "${Red}Error${Color_Off} install_addons.sh into update_prod_to_dev.sh"
exit 1 exit 1
fi fi

View file

@ -84,15 +84,15 @@ check_git() {
fi fi
if [ -z "$output" ]; then if [ -z "$output" ]; then
if [ $# -gt 1 ]; then if [ $# -gt 1 ]; then
echo "PASS - ${REP}/${2}" echo -e "${Green}PASS${Color_Off} - ${REP}/${2}"
else else
echo "PASS - ${REP}" echo -e "${Green}PASS${Color_Off} - ${REP}"
fi fi
else else
if [ $# -gt 1 ]; then if [ $# -gt 1 ]; then
echo -e "${Red}FAIL - ${REP}${2}${Color_Off}" echo -e "${Red}FAIL${Color_Off} - ${REP}${2}"
else else
echo -e "${Red}FAIL - ${REP}${Color_Off}" echo -e "${Red}FAIL${Color_Off} - ${REP}"
fi fi
echo -e "${BRed}${output}${Color_Off}" echo -e "${BRed}${output}${Color_Off}"
cd - >/dev/null || exit cd - >/dev/null || exit

View file

@ -4,9 +4,11 @@
# $3 is directory path to check # $3 is directory path to check
# $4 is generated module name separate by , # $4 is generated module name separate by ,
# $5 optional, the config path # $5 optional, the config path
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
if [[ $# -lt 4 ]]; then if [[ $# -lt 4 ]]; then
echo "ERROR, need 4 arguments: 1-database name, 2-list of module to install, 3-directory to check difference, 4-list of generated module" echo -e "${Red}Error${Color_Off}, need 4 arguments: 1-database name, 2-list of module to install, 3-directory to check difference, 4-list of generated module"
exit 1 exit 1
fi fi
@ -16,14 +18,14 @@ if [[ $# -eq 5 ]]; then
./script/addons/coverage_install_addons_dev.sh "$1" "$2" "$5" ./script/addons/coverage_install_addons_dev.sh "$1" "$2" "$5"
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error ./script/addons/coverage_install_addons_dev.sh ${1} ${2} ${5}" echo -e "${Red}Error${Color_Off} ./script/addons/coverage_install_addons_dev.sh ${1} ${2} ${5}"
exit 1 exit 1
fi fi
else else
./script/addons/coverage_install_addons_dev.sh "$1" "$2" ./script/addons/coverage_install_addons_dev.sh "$1" "$2"
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error ./script/addons/coverage_install_addons_dev.sh ${1} ${2}" echo -e "${Red}Error${Color_Off} ./script/addons/coverage_install_addons_dev.sh ${1} ${2}"
exit 1 exit 1
fi fi
fi fi
@ -32,7 +34,7 @@ fi
./script/code_generator/test_code_generator_update_module.py -m "$4" -d "$3" --datetime "${INIT_DATETIME}" ./script/code_generator/test_code_generator_update_module.py -m "$4" -d "$3" --datetime "${INIT_DATETIME}"
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error ./script/code_generator/test_code_generator_update_module.py ${4} ${3}" echo -e "${Red}Error${Color_Off} ./script/code_generator/test_code_generator_update_module.py ${4} ${3}"
exit 1 exit 1
fi fi
@ -54,6 +56,6 @@ echo "TEST ${2}"
./script/code_generator/check_git_change_code_generator.sh "$3" ./script/code_generator/check_git_change_code_generator.sh "$3"
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error ./script/code_generator/check_git_change_code_generator.sh" echo -e "${Red}Error${Color_Off} ./script/code_generator/check_git_change_code_generator.sh"
exit 1 exit 1
fi fi

View file

@ -4,9 +4,11 @@
# $3 is directory path to check # $3 is directory path to check
# $4 is generated module name separate by , # $4 is generated module name separate by ,
# $5 optional, the config path # $5 optional, the config path
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
if [[ $# -lt 4 ]]; then if [[ $# -lt 4 ]]; then
echo "ERROR, need 4 arguments: 1-database name, 2-list of module to install, 3-directory to check difference, 4-list of generated module" echo -e "${Red}Error${Color_Off}, need 4 arguments: 1-database name, 2-list of module to install, 3-directory to check difference, 4-list of generated module"
exit 1 exit 1
fi fi
@ -16,14 +18,14 @@ if [[ $# -eq 5 ]]; then
./script/addons/install_addons_dev.sh "$1" "$2" "$5" ./script/addons/install_addons_dev.sh "$1" "$2" "$5"
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error ./script/addons/install_addons_dev.sh ${1} ${2} ${5}" echo -e "${Red}Error${Color_Off} ./script/addons/install_addons_dev.sh ${1} ${2} ${5}"
exit 1 exit 1
fi fi
else else
./script/addons/install_addons_dev.sh "$1" "$2" ./script/addons/install_addons_dev.sh "$1" "$2"
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error ./script/addons/install_addons_dev.sh ${1} ${2}" echo -e "${Red}Error${Color_Off} ./script/addons/install_addons_dev.sh ${1} ${2}"
exit 1 exit 1
fi fi
fi fi
@ -32,7 +34,7 @@ fi
./script/code_generator/test_code_generator_update_module.py -m "$4" -d "$3" --datetime "${INIT_DATETIME}" ./script/code_generator/test_code_generator_update_module.py -m "$4" -d "$3" --datetime "${INIT_DATETIME}"
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error ./script/code_generator/test_code_generator_update_module.py ${4} ${3}" echo -e "${Red}Error${Color_Off} ./script/code_generator/test_code_generator_update_module.py ${4} ${3}"
exit 1 exit 1
fi fi
@ -64,6 +66,6 @@ echo "TEST ${2}"
./script/code_generator/check_git_change_code_generator.sh "$3" ./script/code_generator/check_git_change_code_generator.sh "$3"
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error ./script/code_generator/check_git_change_code_generator.sh" echo -e "${Red}Error${Color_Off} ./script/code_generator/check_git_change_code_generator.sh"
exit 1 exit 1
fi fi

View file

@ -1,7 +1,8 @@
#!./.venv/bin/python #!./.venv/bin/python
import argparse import argparse
# import glob import astor
import json
import ast import ast
import logging import logging
import os import os
@ -48,6 +49,19 @@ def get_config():
action="store_true", action="store_true",
help="Will search inherit model", help="Will search inherit model",
) )
parser.add_argument(
"--json",
action="store_true",
help="Return result in json",
)
parser.add_argument(
"--extract_field",
action="store_true",
help=(
"Return list of field for each model, detected. With inherit"
" information"
),
)
parser.add_argument( parser.add_argument(
"-q", "-q",
"--quiet", "--quiet",
@ -108,6 +122,64 @@ def search_and_replace(
return new_file_content return new_file_content
def extract_lambda(node):
result = astor.to_source(node).strip().replace("\n", "")
if result[0] == "(" and result[-1] == ")":
result = result[1:-1]
return result
def fill_search_field(ast_obj, var_name="", py_filename=""):
ast_obj_type = type(ast_obj)
result = None
if ast_obj_type is ast.Str:
result = ast_obj.s
elif ast_obj_type is ast.Lambda:
result = extract_lambda(ast_obj)
elif ast_obj_type is ast.NameConstant:
result = ast_obj.value
elif ast_obj_type is ast.Num:
result = ast_obj.n
elif ast_obj_type is ast.UnaryOp:
if type(ast_obj.op) is ast.USub:
# value is negative
result = ast_obj.operand.n * -1
else:
_logger.warning(
f"Cannot support keyword of variable {var_name} type"
f" {ast_obj_type} operator {type(ast_obj.op)} in filename"
f" {py_filename}."
)
elif ast_obj_type is ast.Name:
result = ast_obj.id
elif ast_obj_type is ast.Attribute:
# Support -> fields.Date.context_today
parent_node = ast_obj
lst_call_lambda = []
while hasattr(parent_node, "value"):
lst_call_lambda.insert(0, parent_node.attr)
parent_node = parent_node.value
lst_call_lambda.insert(0, parent_node.id)
result = ".".join(lst_call_lambda)
elif ast_obj_type is ast.List:
result = [fill_search_field(a, var_name) for a in ast_obj.elts]
elif ast_obj_type is ast.Dict:
result = {
fill_search_field(k, var_name): fill_search_field(
ast_obj.values[i], var_name
)
for (i, k) in enumerate(ast_obj.keys)
}
elif ast_obj_type is ast.Tuple:
result = tuple([fill_search_field(a, var_name) for a in ast_obj.elts])
else:
_logger.warning(
f"Cannot support keyword of variable {var_name} type"
f" {ast_obj_type} in filename {py_filename}."
)
return result
def main(): def main():
config = get_config() config = get_config()
if not os.path.exists(config.directory): if not os.path.exists(config.directory):
@ -116,6 +188,7 @@ def main():
lst_model_name = [] lst_model_name = []
lst_model_inherit_name = [] lst_model_inherit_name = []
lst_search_target = ("_name",) lst_search_target = ("_name",)
dct_model = {}
lst_search_inherit_target = ("_inherit",) if config.with_inherit else [] lst_search_inherit_target = ("_inherit",) if config.with_inherit else []
@ -135,23 +208,29 @@ def main():
if type(children) == ast.ClassDef: if type(children) == ast.ClassDef:
# Detect good _name # Detect good _name
for node in children.body: for node in children.body:
# Search models
if ( if (
type(node) is ast.Assign type(node) is ast.Assign
and node.targets and node.targets
and type(node.targets[0]) is ast.Name and type(node.targets[0]) is ast.Name
# and node.targets[0].id in ("_name",) # and node.targets[0].id in ("_name",)
# and node.targets[0].id in ("_name", "_inherit")
and type(node.value) is ast.Str and type(node.value) is ast.Str
): ):
model_name = ""
is_inherit = False
if ( if (
lst_search_target lst_search_target
and node.targets[0].id in lst_search_target and node.targets[0].id in lst_search_target
): ):
if node.value.s in lst_model_name: if node.value.s in lst_model_name:
is_duplicated = True
_logger.warning( _logger.warning(
"Duplicated model name" "Duplicated model name"
f" {node.value.s} from file {py_file}" f" {node.value.s} from file {py_file}"
) )
else: else:
model_name = node.value.s
lst_model_name.append(node.value.s) lst_model_name.append(node.value.s)
if ( if (
@ -159,13 +238,54 @@ def main():
and node.targets[0].id and node.targets[0].id
in lst_search_inherit_target in lst_search_inherit_target
): ):
is_inherit = True
if node.value.s in lst_model_inherit_name: if node.value.s in lst_model_inherit_name:
_logger.warning( _logger.warning(
"Duplicated model inherit name" "Duplicated model inherit name"
f" {node.value.s} from file {py_file}" f" {node.value.s} from file {py_file}"
) )
else: else:
model_name = node.value.s
lst_model_inherit_name.append(node.value.s) lst_model_inherit_name.append(node.value.s)
dct_fields = {}
if model_name:
dct_model[model_name] = {
"fields": dct_fields,
"model_name": model_name,
"is_inherit": is_inherit,
}
# Detect fields
# TODO do it!
if model_name and (
type(node.value) is ast.Str
and node.value.s == model_name
or type(node.value) is ast.List
and model_name
in [a.s for a in node.value.elts]
):
find_children = children
for sequence, node in enumerate(
find_children.body
):
if (
type(node) is ast.Assign
and type(node.value) is ast.Call
and node.value.func.value.id
== "fields"
):
var_name = node.targets[0].id
d = {
"name": var_name,
"type": node.value.func.attr,
"sequence": sequence,
}
dct_fields[var_name] = d
for keyword in node.value.keywords:
value = fill_search_field(
keyword.value, var_name
)
if value is not None:
d[keyword.arg] = value
lst_model_name.sort() lst_model_name.sort()
lst_model_inherit_name.sort() lst_model_inherit_name.sort()
models_name = "; ".join(lst_model_name) models_name = "; ".join(lst_model_name)
@ -175,12 +295,16 @@ def main():
if ignored_inherit in lst_model_inherit_name: if ignored_inherit in lst_model_inherit_name:
lst_model_inherit_name.remove(ignored_inherit) lst_model_inherit_name.remove(ignored_inherit)
models_inherit_name = "; ".join(lst_model_inherit_name) models_inherit_name = "; ".join(lst_model_inherit_name)
if not models_name: if not config.json:
_logger.warning(f"Missing models class in {config.directory}") if not models_name:
elif not config.quiet: _logger.warning(f"Missing models class in {config.directory}")
# _logger.info(models_name) elif not config.quiet:
print(models_name) # _logger.info(models_name)
print(models_inherit_name) print(models_name)
print(models_inherit_name)
else:
output = json.dumps(dct_model)
print(output)
if config.template_dir: if config.template_dir:
if not os.path.exists(config.template_dir): if not os.path.exists(config.template_dir):

View file

@ -3,6 +3,7 @@ import argparse
import logging import logging
import os import os
import sys import sys
from colorama import Fore, Style
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@ -75,12 +76,14 @@ def main():
if lst_result_wrong: if lst_result_wrong:
_logger.error( _logger.error(
"FAIL - Some modules wasn't updated, did you execute the code" f"{Fore.RED}FAIL{Style.RESET_ALL} - Some modules wasn't updated,"
f" generator? {lst_result_wrong}" f" did you execute the code generator? {lst_result_wrong}"
) )
return -1 return -1
elif lst_result_good: elif lst_result_good:
_logger.info("SUCCESS - All modules are updated.") _logger.info(
f"{Fore.GREEN}SUCCESS{Style.RESET_ALL} - All modules are updated."
)
return 0 return 0

View file

@ -4,6 +4,7 @@ import logging
import os import os
import sys import sys
from xml.dom import Node, minidom from xml.dom import Node, minidom
from colorama import Fore, Style
from code_writer import CodeWriter from code_writer import CodeWriter
@ -109,7 +110,7 @@ def main():
mydoc = minidom.parse(config.file) mydoc = minidom.parse(config.file)
if not mydoc: if not mydoc:
print(f"Error, cannot parse {config.file}") print(f"{Fore.RED}Error{Style.RESET_ALL}, cannot parse {config.file}")
sys.exit(1) sys.exit(1)
cw.emit("from lxml.builder import E") cw.emit("from lxml.builder import E")

View file

@ -1,5 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
. ./env_var.sh . ./env_var.sh
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
ARGS="" ARGS=""
IS_RELEASE=false IS_RELEASE=false
@ -50,7 +52,7 @@ echo "Create docker ${ERPLIBRE_DOCKER_PROD_VERSION}"
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error ./script/docker/docker_build.sh when execute docker_update_version.py" echo -e "${Red}Error${Color_Off} ./script/docker/docker_build.sh when execute docker_update_version.py"
exit 1 exit 1
fi fi
@ -67,4 +69,4 @@ docker build ${ARGS} -f Dockerfile.base -t ${ERPLIBRE_DOCKER_BASE_VERSION} .
docker build ${ARGS} -f Dockerfile.prod.pkg -t ${ERPLIBRE_DOCKER_PROD_VERSION} . docker build ${ARGS} -f Dockerfile.prod.pkg -t ${ERPLIBRE_DOCKER_PROD_VERSION} .
cd - cd -
docker-compose up -d docker compose up -d

View file

@ -7,4 +7,9 @@ BASENAME="${BASENAME//./}"
# Lowercase # Lowercase
BASENAME="${BASENAME,,}" BASENAME="${BASENAME,,}"
docker exec -u root -ti ${BASENAME}_ERPLibre_1 bash docker exec -u root -ti ${BASENAME}-ERPLibre-1 bash
retVal=$?
if [[ $retVal -ne 0 ]]; then
docker exec -u root -ti ${BASENAME}_ERPLibre_1 bash
fi

View file

@ -7,7 +7,15 @@ BASENAME="${BASENAME//./}"
# Lowercase # Lowercase
BASENAME="${BASENAME,,}" BASENAME="${BASENAME,,}"
docker exec -u root -ti ${BASENAME}_ERPLibre_1 /bin/bash -c "\ docker exec -u root -ti ${BASENAME}-ERPLibre-1 /bin/bash -c "\
cd /ERPLibre; \ cd /ERPLibre; \
./docker/repo_manifest_gen_org_prefix_path.py /ERPLibre/addons /etc/odoo/odoo.conf /etc/odoo/odoo.conf; \ ./docker/repo_manifest_gen_org_prefix_path.py /ERPLibre/addons /etc/odoo/odoo.conf /etc/odoo/odoo.conf; \
" "
retVal=$?
if [[ $retVal -ne 0 ]]; then
docker exec -u root -ti ${BASENAME}_ERPLibre_1 /bin/bash -c "\
cd /ERPLibre; \
./docker/repo_manifest_gen_org_prefix_path.py /ERPLibre/addons /etc/odoo/odoo.conf /etc/odoo/odoo.conf; \
"
fi

View file

@ -7,7 +7,15 @@ BASENAME="${BASENAME//./}"
# Lowercase # Lowercase
BASENAME="${BASENAME,,}" BASENAME="${BASENAME,,}"
docker exec -u root -ti ${BASENAME}_ERPLibre_1 /bin/bash -c "\ docker exec -u root -ti ${BASENAME}-ERPLibre-1 /bin/bash -c "\
cd /ERPLibre; \ cd /ERPLibre; \
time make db_list; \ time make db_list; \
" "
retVal=$?
if [[ $retVal -ne 0 ]]; then
docker exec -u root -ti ${BASENAME}_ERPLibre_1 /bin/bash -c "\
cd /ERPLibre; \
time make db_list; \
"
fi

View file

@ -7,7 +7,15 @@ BASENAME="${BASENAME//./}"
# Lowercase # Lowercase
BASENAME="${BASENAME,,}" BASENAME="${BASENAME,,}"
docker exec -u root -ti ${BASENAME}_ERPLibre_1 /bin/bash -c "\ docker exec -u root -ti ${BASENAME}-ERPLibre-1 /bin/bash -c "\
cd /ERPLibre; \ cd /ERPLibre; \
time make test; \ time make test; \
" "
retVal=$?
if [[ $retVal -ne 0 ]]; then
docker exec -u root -ti ${BASENAME}_ERPLibre_1 /bin/bash -c "\
cd /ERPLibre; \
time make test; \
"
fi

View file

@ -7,9 +7,19 @@ BASENAME="${BASENAME//./}"
# Lowercase # Lowercase
BASENAME="${BASENAME,,}" BASENAME="${BASENAME,,}"
docker exec -u root -ti ${BASENAME}_ERPLibre_1 /bin/bash -c "\ docker exec -u root -ti ${BASENAME}-ERPLibre-1 /bin/bash -c "\
cd /ERPLibre; \ cd /ERPLibre; \
./.venv/repo forall -pc 'git status -s'; \ ./.venv/repo forall -pc 'git status -s'; \
echo ''; \ echo ''; \
git status -s; \ git status -s; \
" "
retVal=$?
if [[ $retVal -ne 0 ]]; then
docker exec -u root -ti ${BASENAME}_ERPLibre_1 /bin/bash -c "\
cd /ERPLibre; \
./.venv/repo forall -pc 'git status -s'; \
echo ''; \
git status -s; \
"
fi

View file

@ -3,6 +3,7 @@ from __future__ import print_function
import argparse import argparse
import os.path import os.path
import shutil import shutil
from colorama import Fore, Style
import yaml # pip install PyYAML import yaml # pip install PyYAML
from agithub.GitHub import GitHub # pip install agithub from agithub.GitHub import GitHub # pip install agithub
@ -169,7 +170,10 @@ def fork_and_clone_repo(
parsed_url.repo parsed_url.repo
].forks.post(**args) ].forks.post(**args)
if status == 404: if status == 404:
print("Error when forking repo %s" % forked_repo) print(
f"{Fore.RED}FAIL{Style.RESET_ALL} when forking repo"
f" {forked_repo}"
)
exit(1) exit(1)
else: else:
print("Forked %s to %s" % (upstream_url, forked_repo["html_url"])) print("Forked %s to %s" % (upstream_url, forked_repo["html_url"]))

View file

@ -169,7 +169,6 @@ printf "max_cron_threads = 2\n" >> ${EL_CONFIG_FILE}
if [[ ${EL_INSTALL_NGINX} = "True" ]]; then if [[ ${EL_INSTALL_NGINX} = "True" ]]; then
printf "workers = 2\n" >> ${EL_CONFIG_FILE} printf "workers = 2\n" >> ${EL_CONFIG_FILE}
printf "xmlrpc_interface = 127.0.0.1\n" >> ${EL_CONFIG_FILE} printf "xmlrpc_interface = 127.0.0.1\n" >> ${EL_CONFIG_FILE}
printf "netrpc_interface = 127.0.0.1\n" >> ${EL_CONFIG_FILE}
printf "proxy_mode = True\n" >> ${EL_CONFIG_FILE} printf "proxy_mode = True\n" >> ${EL_CONFIG_FILE}
else else
printf "workers = 0\n" >> ${EL_CONFIG_FILE} printf "workers = 0\n" >> ${EL_CONFIG_FILE}

View file

@ -3,6 +3,7 @@ import argparse
import logging import logging
import os import os
import sys import sys
from colorama import Fore, Style
from git import Repo from git import Repo
@ -91,8 +92,8 @@ def main():
path2 = value2.get("@path") path2 = value2.get("@path")
if path1 != path2: if path1 != path2:
print( print(
f"WARNING id {i}, path of git are different. " f"{Fore.YELLOW}WARNING{Style.RESET_ALL} id {i}, path of git"
f"Input1 {path1}, input2 {path2}" f" are different. Input1 {path1}, input2 {path2}"
) )
continue continue

View file

@ -5,6 +5,7 @@ import os
import webbrowser import webbrowser
from collections import OrderedDict from collections import OrderedDict
from typing import List from typing import List
from colorama import Fore, Style
import git import git
import xmltodict import xmltodict
@ -307,9 +308,10 @@ class GitTool:
url = repo_root.git.remote("get-url", "origin") url = repo_root.git.remote("get-url", "origin")
except Exception as e: except Exception as e:
print( print(
"WARNING: Missing origin remote, use default url " f"{Fore.YELLOW}WARNING{Style.RESET_ALL}: Missing origin"
f"{DEFAULT_REMOTE_URL}. Suggest to add a remote origin: \n" f" remote, use default url {DEFAULT_REMOTE_URL}. Suggest"
f"> git remote add origin {DEFAULT_REMOTE_URL}" " to add a remote origin: \n> git remote add origin"
f" {DEFAULT_REMOTE_URL}"
) )
url = DEFAULT_REMOTE_URL url = DEFAULT_REMOTE_URL
url, url_https, url_git = self.get_url(url) url, url_https, url_git = self.get_url(url)
@ -694,7 +696,10 @@ class GitTool:
continue continue
line_split = line.split(",") line_split = line.split(",")
if len(line_split) != 4: if len(line_split) != 4:
print(f"Error with line {line}, suppose to have only 4 ','.") print(
f"{Fore.RED}Error{Style.RESET_ALL} with line {line},"
" suppose to have only 4 ','."
)
exit(1) exit(1)
url, path, revision, clone_depth = line_split url, path, revision, clone_depth = line_split
# Validate url # Validate url
@ -962,7 +967,10 @@ class GitTool:
parsed_url.repo parsed_url.repo
].forks.post(**args) ].forks.post(**args)
if status == 404: if status == 404:
print("Error when forking repo %s" % forked_repo) print(
f"{Fore.RED}Error{Style.RESET_ALL} when forking repo"
f" {forked_repo}"
)
exit(1) exit(1)
else: else:
try: try:

View file

@ -2,29 +2,7 @@
# https://docs.docker.com/engine/install/debian/ # https://docs.docker.com/engine/install/debian/
# Docker # Docker
sudo apt-get update curl -fsSL https://get.docker.com | sh
sudo apt-get install -y \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
sudo apt-key fingerprint 0EBFCD88
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/debian \
$(lsb_release -cs) \
stable"
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
docker --version
# Docker-compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version
# nginx # nginx
sudo apt-get install -y nginx sudo apt-get install -y nginx

View file

@ -21,6 +21,9 @@ elif [ "18.04" == "${UBUNTU_VERSION}" ]; then
WKHTMLTOX_X64=https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.bionic_amd64.deb WKHTMLTOX_X64=https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.bionic_amd64.deb
elif [[ "${OS}" == "Debian" ]]; then elif [[ "${OS}" == "Debian" ]]; then
WKHTMLTOX_X64=https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-2/wkhtmltox_0.12.6.1-2.bullseye_amd64.deb WKHTMLTOX_X64=https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-2/wkhtmltox_0.12.6.1-2.bullseye_amd64.deb
elif [[ "${OS}" == *"Ubuntu"* ]]; then
echo "Your version of Ubuntu is not supported, only support 18.04, 20.04 and 22.04"
WKHTMLTOX_X64=https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-2/wkhtmltox_0.12.6.1-2.jammy_amd64.deb
else else
echo "Your version of Ubuntu is not supported, only support 18.04, 20.04 and 22.04" echo "Your version of Ubuntu is not supported, only support 18.04, 20.04 and 22.04"
exit 1 exit 1

View file

@ -3,18 +3,18 @@
if [[ "${OSTYPE}" == "linux-gnu" ]]; then if [[ "${OSTYPE}" == "linux-gnu" ]]; then
OS=$(lsb_release -si) OS=$(lsb_release -si)
VERSION=$(cat /etc/issue) VERSION=$(cat /etc/issue)
if [[ "${OS}" == "Ubuntu" ]]; then if [[ "${OS}" == *"Ubuntu"* ]]; then
if [[ "${VERSION}" == Ubuntu\ 18.04* || "${VERSION}" == Ubuntu\ 20.04* || "${VERSION}" == Ubuntu\ 22.04* ]]; 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* ]]; then
echo "\n---- linux-gnu installation process started ----" echo "\n---- linux-gnu installation process started ----"
./script/install/install_debian_dependency.sh ./script/install/install_debian_dependency.sh
else else
echo "Your version is not supported, only support 18.04, 20.04 and 22.04 : ${VERSION}" echo "Your version is not supported, only support 18.04, 20.04 and 22.04 - 23.10 : ${VERSION}"
fi fi
elif [[ "${OS}" == "Debian" ]]; then elif [[ "${OS}" == *"Debian"* ]]; then
./script/install/install_debian_dependency.sh ./script/install/install_debian_dependency.sh
else else
./script/install/install_debian_dependency.sh ./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." echo "Your Linux system is not supported, only support Ubuntu 18.04 or Ubuntu 20.04 or Ubuntu 22.04 - Ubuntu 23.10."
fi fi
elif [[ "${OSTYPE}" == "darwin"* ]]; then elif [[ "${OSTYPE}" == "darwin"* ]]; then
echo "\n---- Darwin installation process started ----" echo "\n---- Darwin installation process started ----"

View file

@ -16,24 +16,8 @@ FLUSH PRIVILEGES;
EOF EOF
# Install docker # Install docker
sudo apt-get update curl -fsSL https://get.docker.com | sh
sudo apt-get install ca-certificates curl gnupg lsb-release dockerd-rootless-setuptool.sh install
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
# Run without root
#sudo groupadd docker
sudo usermod -aG docker "$USER"
#newgrp docker
# Install docker-compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
else
echo "Your version is not supported, only support 18.04 and 20.04 : ${VERSION}"
fi
else else
echo "Your Linux system is not supported, only support Ubuntu 18.04 or Ubuntu 20.04." echo "Your Linux system is not supported, only support Ubuntu 18.04 or Ubuntu 20.04."
fi fi

View file

@ -13,6 +13,9 @@ EL_HOME_ODOO="${EL_HOME}/odoo"
#EL_MINIMAL_ADDONS="False" #EL_MINIMAL_ADDONS="False"
#EL_INSTALL_NGINX="True" #EL_INSTALL_NGINX="True"
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
./script/generate_config.sh ./script/generate_config.sh
#echo -e "\n---- Install Odoo with addons module ----" #echo -e "\n---- Install Odoo with addons module ----"
@ -33,7 +36,7 @@ VENV_REPO_PATH=${VENV_PATH}/repo
VENV_MULTILINGUAL_MARKDOWN_PATH=${VENV_PATH}/multilang_md.py VENV_MULTILINGUAL_MARKDOWN_PATH=${VENV_PATH}/multilang_md.py
#POETRY_PATH=~/.local/bin/poetry #POETRY_PATH=~/.local/bin/poetry
POETRY_PATH=${VENV_PATH}/bin/poetry POETRY_PATH=${VENV_PATH}/bin/poetry
POETRY_VERSION=1.3.1 POETRY_VERSION=1.5.1
echo "Python path version home" echo "Python path version home"
echo ${PYENV_VERSION_PATH} echo ${PYENV_VERSION_PATH}
@ -42,6 +45,9 @@ echo ${LOCAL_PYTHON_EXEC}
if [[ ! -d "${PYENV_PATH}" ]]; then if [[ ! -d "${PYENV_PATH}" ]]; then
echo -e "\n---- Installing pyenv in ${PYENV_PATH} ----" echo -e "\n---- Installing pyenv in ${PYENV_PATH} ----"
# export PYENV_GIT_TAG=v2.3.35
# To change version
# rm ~/.pyenv to uninstall it
curl -L https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash curl -L https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash
fi fi
@ -54,7 +60,7 @@ if [[ ! -d "${PYENV_VERSION_PATH}" ]]; then
echo -e "\n---- Installing python ${PYTHON_VERSION} with pyenv in ${PYENV_VERSION_PATH} ----" echo -e "\n---- Installing python ${PYTHON_VERSION} with pyenv in ${PYENV_VERSION_PATH} ----"
yes n|pyenv install ${PYTHON_VERSION} yes n|pyenv install ${PYTHON_VERSION}
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error when installing pyenv" echo -e "${Red}Error${Color_Off} when installing pyenv"
exit 1 exit 1
fi fi
fi fi
@ -119,6 +125,8 @@ if [[ ! -f "${POETRY_PATH}" ]]; then
echo "Poetry installation error." echo "Poetry installation error."
exit 1 exit 1
fi fi
# Fix pip installation missing package
${VENV_PATH}/bin/pip install selenium
fi fi
# Delete artifacts created by pip, cause error in next "poetry install" # Delete artifacts created by pip, cause error in next "poetry install"

View file

@ -2,10 +2,13 @@
. ./env_var.sh . ./env_var.sh
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
./script/install/install_locally.sh ./script/install/install_locally.sh
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error ./script/install/install_locally.sh" echo -e "${Red}Error${Color_Off} ./script/install/install_locally.sh"
exit 1 exit 1
fi fi
@ -13,7 +16,7 @@ fi
./script/manifest/update_manifest_local_dev.sh ./script/manifest/update_manifest_local_dev.sh
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error manifest update, check git-repo." echo -e "${Red}Error${Color_Off} manifest update, check git-repo."
exit 1 exit 1
fi fi

View file

@ -2,10 +2,13 @@
. ./env_var.sh . ./env_var.sh
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
./script/install/install_locally.sh ./script/install/install_locally.sh
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error ./script/install/install_locally.sh" echo -e "${Red}Error${Color_Off} ./script/install/install_locally.sh"
exit 1 exit 1
fi fi
@ -13,6 +16,6 @@ fi
./script/manifest/update_manifest_prod.sh ./script/manifest/update_manifest_prod.sh
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error manifest update, check git-repo." echo -e "${Red}Error${Color_Off} manifest update, check git-repo."
exit 1 exit 1
fi fi

View file

@ -1,29 +1,8 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# From https://docs.docker.com/engine/install/ubuntu/ # From https://docs.docker.com/engine/install/ubuntu/
sudo apt-get update # Docker
sudo apt-get install -y \ curl -fsSL https://get.docker.com | sh
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo apt-key fingerprint 0EBFCD88
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
docker --version
# Docker-compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version
# nginx # nginx
sudo apt-get install -y nginx sudo apt-get install -y nginx

View file

@ -39,6 +39,27 @@ async def run_command_get_output(*args, cwd=None):
return stdout.decode() return stdout.decode()
async def run_shell_get_output(cmd, cwd=None):
if cwd is not None:
process = await asyncio.create_subprocess_shell(
cmd,
# stdout must a pipe to be accessible as process.stdout
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
cwd=cwd,
)
else:
process = await asyncio.create_subprocess_shell(
cmd,
# stdout must a pipe to be accessible as process.stdout
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
)
# Wait for the subprocess to finish
stdout, stderr = await process.communicate()
return stdout.decode()
async def run_command_get_output_and_status(*args, cwd=None): async def run_command_get_output_and_status(*args, cwd=None):
if cwd is not None: if cwd is not None:
process = await asyncio.create_subprocess_exec( process = await asyncio.create_subprocess_exec(
@ -60,13 +81,18 @@ async def run_command_get_output_and_status(*args, cwd=None):
return stdout.decode(), stderr.decode(), process.returncode return stdout.decode(), stderr.decode(), process.returncode
def print_summary_task(task_list): def print_summary_task(task_list, lst_task_name=None):
for task in task_list: for i, task in enumerate(task_list):
print(task.cr_code.co_name) if lst_task_name:
task_name = lst_task_name[i]
print(f"{i} - {task.cr_code.co_name} - {task_name}")
else:
print(f"{i} - {task.cr_code.co_name}")
def execute(config, lst_task, use_uvloop=False): def execute(config, lst_task, use_uvloop=False):
error_detected = False
return_value = None
if not config.no_parallel and asyncio.get_event_loop().is_closed(): if not config.no_parallel and asyncio.get_event_loop().is_closed():
asyncio.set_event_loop(asyncio.new_event_loop()) asyncio.set_event_loop(asyncio.new_event_loop())
@ -85,14 +111,23 @@ def execute(config, lst_task, use_uvloop=False):
if use_uvloop: if use_uvloop:
uvloop.install() uvloop.install()
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
# Can fix when cannot attach child to loop
# if sys.platform != "win32":
# policy = asyncio.get_event_loop_policy()
# watcher = asyncio.SafeChildWatcher()
# watcher.attach_loop(loop)
# policy.set_child_watcher(watcher)
if config.debug: if config.debug:
loop.set_debug(True) loop.set_debug(True)
try: try:
commands = asyncio.gather(*lst_task) commands = asyncio.gather(*lst_task)
return_value = loop.run_until_complete(commands) return_value = loop.run_until_complete(commands)
except RuntimeError as e:
error_detected = True
print(e)
finally: finally:
loop.close() loop.close()
return return_value return return_value, error_detected
class AsyncioPool: class AsyncioPool:

View file

@ -1,4 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
# This will format all python file # This will format all python file
# argument 1: directory or file to format # argument 1: directory or file to format
NPROC=$(nproc) NPROC=$(nproc)
@ -6,6 +9,6 @@ source ./script/OCA_maintainer-tools/env/bin/activate
oca-autopep8 -j ${NPROC} --max-line-length 79 -ari $@ oca-autopep8 -j ${NPROC} --max-line-length 79 -ari $@
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error oca-autopep8 format" echo -e "${Red}Error${Color_Off} oca-autopep8 format"
exit 1 exit 1
fi fi

View file

@ -1,10 +1,13 @@
#!/usr/bin/env bash #!/usr/bin/env bash
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
# This will format all python file # This will format all python file
# argument 1: directory or file to format # argument 1: directory or file to format
source ./.venv/bin/activate source ./.venv/bin/activate
black -l 79 --preview -t py37 "$@" black -l 79 --preview -t py37 "$@"
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error black format" echo -e "${Red}Error${Color_Off} black format"
exit 1 exit 1
fi fi

View file

@ -1,9 +1,12 @@
#!/usr/bin/env bash #!/usr/bin/env bash
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
# This will format all js,css,html # This will format all js,css,html
# argument 1: directory or file to format # argument 1: directory or file to format
./node_modules/.bin/prettier --tab-width 4 --print-width 120 --no-bracket-spacing --write "$@" ./node_modules/.bin/prettier --tab-width 4 --print-width 120 --no-bracket-spacing --write "$@"
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error prettier format" echo -e "${Red}Error${Color_Off} prettier format"
exit 1 exit 1
fi fi

View file

@ -1,4 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
# This will format all xml # This will format all xml
# argument 1: directory or file to format # argument 1: directory or file to format
STR_ARG="'$*'" STR_ARG="'$*'"
@ -12,6 +15,6 @@ else
fi fi
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error prettier-xml format" echo -e "${Red}Error${Color_Off} prettier-xml format"
exit 1 exit 1
fi fi

View file

@ -1,4 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
echo " echo "
===> ${@} ===> ${@}
" "
@ -10,6 +13,6 @@ echo "
" "
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error make ${@}" echo -e "${Red}Error${Color_Off} make ${@}"
exit 1 exit 1
fi fi

View file

@ -3,9 +3,9 @@
working_path=$(readlink -f .) working_path=$(readlink -f .)
paths=( paths=(
"${working_path}/" "${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/ERPLibre_erplibre_addons"
"${working_path}/addons/TechnoLibre_odoo-code-generator"
"${working_path}/addons/TechnoLibre_odoo-code-generator-template"
# "${working_path}/addons/OCA_server-tools" # "${working_path}/addons/OCA_server-tools"
) )

View file

@ -1,10 +1,13 @@
#!/usr/bin/env bash #!/usr/bin/env bash
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
./.venv/bin/poetry add -vv $(grep -v ";" ./.venv/build_dependency.txt | grep -v "*" ) ./.venv/bin/poetry add -vv $(grep -v ";" ./.venv/build_dependency.txt | grep -v "*" )
# poetry add -vv $(grep -v ";" ./.venv/build_dependency.txt | grep -v "*" | sed 's/==/@^/' ) # poetry add -vv $(grep -v ";" ./.venv/build_dependency.txt | grep -v "*" | sed 's/==/@^/' )
# poetry export -f ./.venv/build_dependency.txt --dev | poetry run -- pip install -r /dev/stdin # poetry export -f ./.venv/build_dependency.txt --dev | poetry run -- pip install -r /dev/stdin
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error ./script/poetry/poetry_add_build_dependency.sh" echo -e "${Red}Error${Color_Off} ./script/poetry/poetry_add_build_dependency.sh"
cat ./.venv/build_dependency.txt cat ./.venv/build_dependency.txt
exit 1 exit 1
fi fi

View file

@ -3,9 +3,9 @@ import argparse
import ast import ast
import logging import logging
import os import os
import sys
from collections import OrderedDict, defaultdict from collections import OrderedDict, defaultdict
from pathlib import Path from pathlib import Path
from colorama import Fore, Style
import iscompatible import iscompatible
import toml import toml
@ -267,8 +267,8 @@ def combine_requirements(config):
] ]
) )
print( print(
f"WARNING - Not compatible {str_versions} - " f"{Fore.YELLOW}WARNING{Style.RESET_ALL} - Not"
f"{str_result_choose}." f" compatible {str_versions} - {str_result_choose}."
) )
elif len(lst_version_requirement) == 1: elif len(lst_version_requirement) == 1:
result = lst_version_requirement[0][0] result = lst_version_requirement[0][0]

View file

@ -229,7 +229,7 @@ def main():
clone_repo(i, a, config.force_git_fetch) clone_repo(i, a, config.force_git_fetch)
for i, a in enumerate(lst_repo_url) for i, a in enumerate(lst_repo_url)
] ]
lst_repo_path = lib_asyncio.execute( lst_repo_path, has_asyncio_error = lib_asyncio.execute(
config, lst_task_clone, use_uvloop=True config, lst_task_clone, use_uvloop=True
) )
@ -268,13 +268,15 @@ def main():
min_i = i * MAX_COROUTINE min_i = i * MAX_COROUTINE
max_i = min((i + 1) * MAX_COROUTINE, len(lst_task)) max_i = min((i + 1) * MAX_COROUTINE, len(lst_task))
_logger.info(f"Partial execution {min_i} to {max_i}") _logger.info(f"Partial execution {min_i} to {max_i}")
tpl_result = lib_asyncio.execute( tpl_result, has_asyncio_error = lib_asyncio.execute(
config, lst_task[min_i:max_i], use_uvloop=True config, lst_task[min_i:max_i], use_uvloop=True
) )
lst_result += tpl_result lst_result += tpl_result
tpl_result = lst_result tpl_result = lst_result
else: else:
tpl_result = lib_asyncio.execute(config, lst_task, use_uvloop=True) tpl_result, has_asyncio_error = lib_asyncio.execute(
config, lst_task, use_uvloop=True
)
_logger.info("Analyse information") _logger.info("Analyse information")
dct_result = defaultdict(lambda: defaultdict(int)) dct_result = defaultdict(lambda: defaultdict(int))
dct_result_unique = defaultdict(set) dct_result_unique = defaultdict(set)

View file

@ -0,0 +1,20 @@
#!/bin/bash
USE_LOCATE=true
if [ "$USE_LOCATE" == false ]
then
find "/" -name "docker-compose.yml" -type f -print 2>/dev/null | grep -v .repo | grep -v /var/lib/docker | xargs -I {} sh -c 'grep -l "ERPLibre" "{}" 2>/dev/null || true'
# SEARCH_PATH="/"
# find "$SEARCH_PATH" -name "docker-compose.yml" -type f 2>/dev/null | grep -v .repo | while read -r file; do
# grep -q "ERPLibre" "$file" && echo "$file"
# done
elif [ "$USE_LOCATE" == true ]
then
locate -b -r "^docker-compose\.yml$" | grep -v .repo | grep -v /var/lib/docker | xargs -I {} sh -c "grep -l \"ERPLibre\" \"{}\" 2>/dev/null || true"
# locate -b -r '^docker-compose\.yml$' | grep -v .repo | while read -r file; do
# if [ -f "$file" ]; then
# grep -q 'ERPLibre' "$file" && echo "$file"
# fi
# done
fi

View file

@ -0,0 +1,149 @@
{
"lst_test": [
{
"run_command": true,
"test_name": "helloworld_test",
"sequence": 10,
"script": "./test/code_generator/hello_world.sh",
"note": "Test helloword_test Will cause conflict with the other because write in code_generator_demo/hooks.py"
},
{
"run_test_exec": true,
"test_name": "code_generator_theme_test",
"path_module_check": "./addons/TechnoLibre_odoo-code-generator-template",
"generated_module": "theme_website_demo_code_generator",
"tested_module": "code_generator_demo_theme_website"
},
{
"run_test_exec": true,
"test_name": "code_generator_demo_test",
"path_module_check": "./addons/TechnoLibre_odoo-code-generator-template",
"generated_module": "code_generator_demo",
"tested_module": "code_generator_demo"
},
{
"run_test_exec": true,
"test_name": "code_generator_data_test",
"path_module_check": "./addons/TechnoLibre_odoo-code-generator-template",
"generated_module": "demo_helpdesk_data",
"tested_module": "code_generator_demo_export_helpdesk"
},
{
"run_test_exec": true,
"test_name": "code_generator_data_part_2_test",
"path_module_check": "./addons/TechnoLibre_odoo-code-generator-template",
"generated_module": "demo_website_data",
"tested_module": "code_generator_demo_export_website",
"note": "Merge to code_generator_data_test when fix double export data."
},
{
"run_test_exec": true,
"test_name": "code_generator_inherit_test",
"path_module_check": "./addons/TechnoLibre_odoo-code-generator-template",
"generated_module": "demo_internal_inherit",
"tested_module": "code_generator_demo_internal_inherit"
},
{
"run_test_exec": true,
"test_name": "code_generator_template_demo_internal",
"path_module_check": "./addons/TechnoLibre_odoo-code-generator-template",
"generated_module": "code_generator_demo_internal",
"tested_module": "code_generator_template_demo_internal",
"search_class_module": "demo_internal",
"init_module_name": "demo_internal"
},
{
"run_test_exec": true,
"test_name": "code_generator_template_demo_portal",
"path_module_check": "./addons/TechnoLibre_odoo-code-generator-template",
"generated_module": "code_generator_demo_portal",
"tested_module": "code_generator_template_demo_portal",
"search_class_module": "demo_portal",
"init_module_name": "demo_portal"
},
{
"run_test_exec": true,
"test_name": "mariadb_test_template",
"path_module_check": "./addons/TechnoLibre_odoo-code-generator-template",
"generated_module": "code_generator_demo_mariadb_sql_example_1",
"tested_module": "code_generator_template_demo_mariadb_sql_example_1",
"search_class_module": "demo_mariadb_sql_example_1",
"init_module_name": "code_generator_portal,demo_mariadb_sql_example_1"
},
{
"run_test_exec": true,
"test_name": "mariadb_test_migrator",
"path_module_check": "./addons/TechnoLibre_odoo-code-generator-template",
"generated_module": "demo_mariadb_sql_example_1",
"tested_module": "code_generator_migrator_demo_mariadb_sql_example_1",
"script_after_init_check": "./script/database/restore_mariadb_sql_example_1.sh",
"init_module_name": "code_generator_portal"
},
{
"run_test_exec": true,
"test_name": "mariadb_test_code_generator",
"path_module_check": "./addons/TechnoLibre_odoo-code-generator-template",
"generated_module": "demo_mariadb_sql_example_1",
"tested_module": "code_generator_demo_mariadb_sql_example_1",
"init_module_name": "code_generator_portal"
},
{
"run_test_exec": true,
"test_name": "code_generator_template_demo_internal_inherit",
"path_module_check": "./addons/TechnoLibre_odoo-code-generator-template",
"generated_module": "code_generator_demo_internal_inherit",
"tested_module": "code_generator_template_demo_internal_inherit",
"search_class_module": "demo_internal_inherit",
"init_module_name": "demo_internal_inherit"
},
{
"run_test_exec": true,
"test_name": "code_generator_template_demo_sysadmin_cron",
"path_module_check": "./addons/OCA_server-tools/auto_backup",
"generated_module": "code_generator_auto_backup",
"generated_path": "./addons/OCA_server-tools/",
"tested_module": "code_generator_template_demo_sysadmin_cron",
"search_class_module": "auto_backup",
"init_module_name": "auto_backup",
"install_path": "./addons/TechnoLibre_odoo-code-generator-template"
},
{
"run_test_exec": true,
"test_name": "code_generator_export_website_attachments_test",
"path_module_check": "./addons/TechnoLibre_odoo-code-generator-template",
"generated_module": "demo_website_attachments_data",
"tested_module": "code_generator_demo_export_website_attachments",
"restore_db_image_name": "test_website_attachments"
},
{
"run_test_exec": true,
"test_name": "code_generator_demo_generic_test",
"path_module_check": "./addons/TechnoLibre_odoo-code-generator-template",
"generated_module": "demo_internal,demo_portal",
"tested_module": "code_generator_demo_internal,code_generator_demo_portal"
},
{
"run_test_exec": true,
"test_name": "code_generator_website_snippet_test",
"path_module_check": "./addons/TechnoLibre_odoo-code-generator-template",
"generated_module": "demo_website_leaflet,demo_website_snippet,demo_website_multiple_snippet",
"tested_module": "code_generator_demo_website_leaflet,code_generator_demo_website_snippet,code_generator_demo_website_multiple_snippet",
"file_to_restore": "demo_portal/i18n/demo_portal.pot,demo_portal/i18n/fr_CA.po",
"file_to_restore_origin": true,
"note": "Because code_generator_demo_website_multiple_snippet depend on code_generator_demo_portal, it will execute it and this delete file demo_portal/i18n/demo_portal.pot and demo_portal/i18n/fr_CA.po"
},
{
"run_test_exec": true,
"test_name": "demo_test",
"path_module_check": "./addons/TechnoLibre_odoo-code-generator-template",
"init_module_name": "demo_helpdesk_data,demo_internal,demo_internal_inherit,demo_mariadb_sql_example_1,demo_portal,demo_website_data,demo_website_leaflet,demo_website_snippet"
},
{
"run_test_exec": true,
"test_name": "code_generator_auto_backup_test",
"path_module_check": "./addons/OCA_server-tools/auto_backup",
"generated_module": "auto_backup",
"tested_module": "code_generator_auto_backup"
}
]
}

View file

@ -9,11 +9,13 @@ import sys
import tempfile import tempfile
import time import time
import uuid import uuid
import json
from typing import Tuple from typing import Tuple
from collections import defaultdict
import aioshutil import aioshutil
import git import git
from colorama import Fore from colorama import Fore, Style
new_path = os.path.normpath( new_path = os.path.normpath(
os.path.join(os.path.dirname(__file__), "..", "..") os.path.join(os.path.dirname(__file__), "..", "..")
@ -26,6 +28,7 @@ logging.basicConfig(level=logging.DEBUG)
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
LOG_FILE = "./.venv/make_test.log" LOG_FILE = "./.venv/make_test.log"
CONFIG_TESTCASE_JSON = "./script/test/config_testcase.json"
def get_config(): def get_config():
@ -71,6 +74,17 @@ def get_config():
action="store_true", action="store_true",
help="Enable asyncio debugging", help="Enable asyncio debugging",
) )
parser.add_argument(
"--json_model",
help="Model of data to run test in json",
)
parser.add_argument(
"--output_result_dir",
help=(
"A path of existing directory, will export a file per test with"
" status/result and log."
),
)
args = parser.parse_args() args = parser.parse_args()
return args return args
@ -136,14 +150,14 @@ def check_result(task_list, tpl_result):
status = False status = False
if lst_warning: if lst_warning:
print(f"{Fore.YELLOW}{len(lst_warning)} WARNING{Fore.RESET}") print(f"{Fore.YELLOW}{len(lst_warning)} WARNING{Style.RESET_ALL}")
i = 0 i = 0
for warning in lst_warning: for warning in lst_warning:
i += 1 i += 1
print(f"[{i}]{warning}") print(f"[{i}]{warning}")
if lst_error: if lst_error:
print(f"{Fore.RED}{len(lst_error)} ERROR{Fore.RESET}") print(f"{Fore.RED}{len(lst_error)} ERROR{Style.RESET_ALL}")
i = 0 i = 0
for error in lst_error: for error in lst_error:
i += 1 i += 1
@ -151,13 +165,13 @@ def check_result(task_list, tpl_result):
if lst_error or lst_warning: if lst_error or lst_warning:
str_result = ( str_result = (
f"{Fore.RED}{len(lst_error)} ERROR" f"{Fore.RED}{len(lst_error)} ERROR{Style.RESET_ALL}"
f" {Fore.YELLOW}{len(lst_warning)} WARNING" f" {Fore.YELLOW}{len(lst_warning)} WARNING{Style.RESET_ALL}"
) )
else: else:
str_result = f"{Fore.GREEN}SUCCESS 🍰" str_result = f"{Fore.GREEN}SUCCESS{Style.RESET_ALL} 🍰"
print(f"{Fore.BLUE}Summary TEST {str_result}{Fore.RESET}") print(f"{Fore.BLUE}Summary TEST {str_result}{Style.RESET_ALL}")
return status return status
@ -168,7 +182,11 @@ def print_log(lst_task, tpl_result):
with open(LOG_FILE, "w") as f: with open(LOG_FILE, "w") as f:
for i, task in enumerate(lst_task): for i, task in enumerate(lst_task):
result = tpl_result[i] result = tpl_result[i]
status_str = "PASS" if not result[1] else "FAIL" status_str = (
f"{Fore.GREEN}PASS{Style.RESET_ALL}"
if not result[1]
else f"{Fore.RED}FAIL{Style.RESET_ALL}"
)
f.write( f.write(
f"\nTest execution {i + 1} - {status_str} -" f"\nTest execution {i + 1} - {status_str} -"
f" {task.cr_code.co_name}\n\n" f" {task.cr_code.co_name}\n\n"
@ -178,6 +196,33 @@ def print_log(lst_task, tpl_result):
f.write("\n") f.write("\n")
def print_log_output_into_dir(tpl_result, output_dir):
date_now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
for i, result in enumerate(tpl_result):
log = result[0]
status = result[1]
test_name = result[2]
test_name_file_name = test_name.replace(" ", "")
time_execution = result[3]
log_file = os.path.join(output_dir, test_name_file_name)
with open(log_file, "w") as f:
f.write(f"{status}\n")
f.write(f"{test_name}\n")
f.write(f"{time_execution}\n")
f.write(f"{date_now}\n")
status_str = (
f"{Fore.GREEN}PASS{Style.RESET_ALL}"
if not status
else f"{Fore.RED}FAIL{Style.RESET_ALL}"
)
f.write(
f"\nTest execution {i + 1} - {status_str} - {test_name}\n\n"
)
if log:
f.write(log)
f.write("\n")
async def run_command(*args, test_name=None): async def run_command(*args, test_name=None):
# Create subprocess # Create subprocess
start_time = time.time() start_time = time.time()
@ -195,7 +240,11 @@ async def run_command(*args, test_name=None):
# Return stdout + stderr, returncode # Return stdout + stderr, returncode
str_out = "\n" + stdout.decode().strip() + "\n" if stdout else "" str_out = "\n" + stdout.decode().strip() + "\n" if stdout else ""
str_err = "\n" + stderr.decode().strip() + "\n" if stderr else "" str_err = "\n" + stderr.decode().strip() + "\n" if stderr else ""
status_str = "FAIL" if process.returncode else "PASS" status_str = (
f"{Fore.RED}FAIL{Style.RESET_ALL}"
if process.returncode
else f"{Fore.GREEN}PASS{Style.RESET_ALL}"
)
if test_name: if test_name:
str_output_init = ( str_output_init = (
f"\n\n{status_str} [{test_name}] [{diff_sec:.3f}s] Execute" f"\n\n{status_str} [{test_name}] [{diff_sec:.3f}s] Execute"
@ -255,7 +304,6 @@ def update_config(
async def test_exec( async def test_exec(
config,
path_module_check: str, path_module_check: str,
generated_module=None, generated_module=None,
generate_path=None, generate_path=None,
@ -263,14 +311,19 @@ async def test_exec(
search_class_module=None, search_class_module=None,
script_after_init_check=None, script_after_init_check=None,
lst_init_module_name=None, lst_init_module_name=None,
file_to_restore=None,
file_to_restore_origin=False,
test_name=None, test_name=None,
install_path=None, install_path=None,
run_in_sandbox=False, run_in_sandbox=True,
restore_db_image_name="erplibre_base", restore_db_image_name="erplibre_base",
) -> Tuple[str, int]: keep_cache=False,
coverage=False,
) -> Tuple[str, int, str, float]:
time_init = datetime.datetime.now()
test_result = "" test_result = ""
test_status = 0 test_status = 0
new_destination_path = None origin_path_module_check = path_module_check
if search_class_module: if search_class_module:
if install_path is not None: if install_path is not None:
path_template_to_generate = os.path.join( path_template_to_generate = os.path.join(
@ -300,7 +353,7 @@ async def test_exec(
destination_path = None destination_path = None
temp_dir_name = None temp_dir_name = None
if run_in_sandbox: if run_in_sandbox:
if config.keep_cache: if keep_cache:
temp_dir = tempfile.mkdtemp() temp_dir = tempfile.mkdtemp()
temp_dir_name = temp_dir temp_dir_name = temp_dir
else: else:
@ -313,9 +366,10 @@ async def test_exec(
lst_path_to_add_config = [] lst_path_to_add_config = []
lst_path_to_remove_config = [] lst_path_to_remove_config = []
if not os.path.exists(path_module_check): if not os.path.exists(path_module_check):
# TODO wrong return
return ( return (
f"Error var path_module_check '{path_module_check}' not" f"{Fore.RED}Error{Style.RESET_ALL} var path_module_check"
" exist.", f" '{path_module_check}' not exist.",
-1, -1,
) )
@ -369,9 +423,10 @@ async def test_exec(
) )
) )
if not s_lst_path_tested_module: if not s_lst_path_tested_module:
# TODO wrong return
return ( return (
f"Error cannot find module '{path_module_check}' not" f"{Fore.RED}Error{Style.RESET_ALL} cannot find module"
" exist.", f" '{path_module_check}' not exist.",
-1, -1,
) )
else: else:
@ -431,6 +486,12 @@ async def test_exec(
s_first_path = destination_path s_first_path = destination_path
hook_file = os.path.join(new_s_first_path, "hooks.py") hook_file = os.path.join(new_s_first_path, "hooks.py")
if not os.path.exists(hook_file):
test_status += 1
test_result += f"Hook file '{hook_file}' not exist."
delta = datetime.datetime.now() - time_init
total_time = delta.total_seconds()
return test_result, test_status, test_name, total_time
with open(hook_file) as hook: with open(hook_file) as hook:
hook_line = hook.read() hook_line = hook.read()
has_template = ( has_template = (
@ -460,6 +521,7 @@ async def test_exec(
) )
break break
if nb_space_indentation is None: if nb_space_indentation is None:
# TODO wrong return
return ( return (
f"Cannot find keys '{lst_f_key}' in" f"Cannot find keys '{lst_f_key}' in"
f" {hook_file}", f" {hook_file}",
@ -520,6 +582,12 @@ async def test_exec(
lst_path_to_remove_config=lst_path_to_remove_config, lst_path_to_remove_config=lst_path_to_remove_config,
module_name=generated_module, module_name=generated_module,
) )
if not os.path.exists(new_config_path):
test_status += 1
test_result += f"Config file '{new_config_path}' not exist."
delta = datetime.datetime.now() - time_init
total_time = delta.total_seconds()
return test_result, test_status, test_name, total_time
else: else:
new_config_path = None new_config_path = None
@ -555,7 +623,9 @@ async def test_exec(
# Leave when detect anomaly in check before start # Leave when detect anomaly in check before start
if test_status: if test_status:
return test_result, test_status delta = datetime.datetime.now() - time_init
total_time = delta.total_seconds()
return test_result, test_status, test_name, total_time
# Execute script before start # Execute script before start
if script_after_init_check and not test_status: if script_after_init_check and not test_status:
@ -582,7 +652,7 @@ async def test_exec(
if not test_status and lst_init_module_name: if not test_status and lst_init_module_name:
# Install required module # Install required module
str_test = ",".join(lst_init_module_name) str_test = ",".join(lst_init_module_name)
if config.coverage: if coverage:
script_name = ( script_name = (
"./script/addons/coverage_install_addons_dev.sh" "./script/addons/coverage_install_addons_dev.sh"
if tested_module if tested_module
@ -638,7 +708,7 @@ async def test_exec(
if not test_status and tested_module and generated_module: if not test_status and tested_module and generated_module:
cmd = ( cmd = (
"./script/code_generator/coverage_install_and_test_code_generator.sh" "./script/code_generator/coverage_install_and_test_code_generator.sh"
if config.coverage if coverage
else "./script/code_generator/install_and_test_code_generator.sh" else "./script/code_generator/install_and_test_code_generator.sh"
) )
# Finally, the test # Finally, the test
@ -677,7 +747,28 @@ async def test_exec(
test_result += res test_result += res
test_status += status test_status += status
return test_result, test_status if file_to_restore:
lst_file_to_ignore = file_to_restore.strip().split(",")
if file_to_restore_origin:
repo_demo_portal = git.Repo(origin_path_module_check)
else:
repo_demo_portal = git.Repo(path_module_check)
status_to_check = repo_demo_portal.git.status("-s")
if all([f"D {a}" in status_to_check for a in lst_file_to_ignore]):
# Revert it
for file_name in lst_file_to_ignore:
repo_demo_portal.git.checkout(file_name)
else:
test_status += 1
test_result += (
f"\n\n{Fore.RED}FAIL{Style.RESET_ALL} - inspect to delete file"
f" {lst_file_to_ignore}"
)
delta = datetime.datetime.now() - time_init
total_time = delta.total_seconds()
return test_result, test_status, test_name, total_time
def check_git_change(): def check_git_change():
@ -707,534 +798,133 @@ def check_git_change():
return not status return not status
# START TEST async def run_test_command(
script_path: str, test_name: str
) -> Tuple[str, int, str, float]:
time_init = datetime.datetime.now()
res, status = await run_command(script_path, test_name=test_name)
delta = datetime.datetime.now() - time_init
total_time = delta.total_seconds()
return res, status, test_name, total_time
async def run_demo_test(config) -> Tuple[str, int]: def run_all_test(config) -> bool:
lst_test_name = [ if config.json_model:
"demo_helpdesk_data", json_model = config.json_model
"demo_internal", else:
"demo_internal_inherit", with open(CONFIG_TESTCASE_JSON) as config_json:
"demo_mariadb_sql_example_1", json_model = config_json.read()
"demo_portal", dct_model_test = json.loads(json_model)
"demo_website_data", lst_test = dct_model_test.get("lst_test")
"demo_website_leaflet", if not lst_test:
"demo_website_snippet", _logger.error("Model missing attribute 'lst_test'.")
] return False
res, status = await test_exec( # Sort test by sequence
config, dct_task = defaultdict(list)
"./addons/TechnoLibre_odoo-code-generator-template", dct_task_name = defaultdict(list)
lst_init_module_name=lst_test_name, for dct_test in lst_test:
test_name="demo_test", sequence = dct_test.get("sequence", 0)
) cb_coroutine = None
test_name = None
return res, status if dct_test.get("run_command"):
test_name = dct_test.get("test_name")
if not test_name:
async def run_code_generator_migrator_demo_mariadb_sql_example_1_test( raise ValueError(
config, "Missing attribute 'test_name' into the json_model."
) -> Tuple[str, int]: )
# Migrator script = dct_test.get("script")
res, status = await test_exec( if not script:
config, raise ValueError(
"./addons/TechnoLibre_odoo-code-generator-template", "Missing attribute 'script' into the json_model."
generated_module="demo_mariadb_sql_example_1", )
tested_module="code_generator_migrator_demo_mariadb_sql_example_1", cb_coroutine = run_test_command(script, test_name)
script_after_init_check=( elif dct_test.get("run_test_exec"):
"./script/database/restore_mariadb_sql_example_1.sh" path_module_check = dct_test.get("path_module_check")
), if not path_module_check:
lst_init_module_name=[ raise ValueError(
"code_generator_portal", "Missing attribute 'path_module_check' into the"
], " json_model."
test_name="mariadb_test-migrator", )
run_in_sandbox=True, generated_module = dct_test.get("generated_module")
) generate_path = dct_test.get("generate_path")
tested_module = dct_test.get("tested_module")
return res, status search_class_module = dct_test.get("search_class_module")
script_after_init_check = dct_test.get("script_after_init_check")
init_module_name = dct_test.get("init_module_name")
async def run_code_generator_template_demo_mariadb_sql_example_1_test( lst_init_module_name = None
config, if init_module_name:
) -> Tuple[str, int]: lst_init_module_name = init_module_name.split(",")
# Template test_name = dct_test.get("test_name")
res, status = await test_exec( if not test_name:
config, raise ValueError(
"./addons/TechnoLibre_odoo-code-generator-template", "Missing attribute 'test_name' into the json_model."
generated_module="code_generator_demo_mariadb_sql_example_1", )
tested_module="code_generator_template_demo_mariadb_sql_example_1", file_to_restore = dct_test.get("file_to_restore")
search_class_module="demo_mariadb_sql_example_1", file_to_restore_origin = dct_test.get(
lst_init_module_name=[ "file_to_restore_origin", False
"code_generator_portal",
"demo_mariadb_sql_example_1",
],
test_name="mariadb_test-template",
run_in_sandbox=True,
)
return res, status
async def run_code_generator_demo_mariadb_sql_example_1_test(
config,
) -> Tuple[str, int]:
# Code generator
res, status = await test_exec(
config,
"./addons/TechnoLibre_odoo-code-generator-template",
generated_module="demo_mariadb_sql_example_1",
lst_init_module_name=[
"code_generator_portal",
],
tested_module="code_generator_demo_mariadb_sql_example_1",
test_name="mariadb_test-code-generator",
run_in_sandbox=True,
)
return res, status
async def run_code_generator_data_test(config) -> Tuple[str, int]:
test_result = ""
test_status = 0
lst_generated_module = [
"demo_helpdesk_data",
# "demo_website_data",
]
lst_tested_module = [
"code_generator_demo_export_helpdesk",
# "code_generator_demo_export_website",
]
# Multiple
res, status = await test_exec(
config,
"./addons/TechnoLibre_odoo-code-generator-template",
generated_module=",".join(lst_generated_module),
tested_module=",".join(lst_tested_module),
test_name="code_generator_data_test",
run_in_sandbox=True,
)
test_result += res
test_status += status
return test_result, test_status
async def run_code_generator_data_test_part_2(config) -> Tuple[str, int]:
# TODO merge this test into run_code_generator_data_test
test_result = ""
test_status = 0
lst_generated_module = [
"demo_website_data",
]
lst_tested_module = [
"code_generator_demo_export_website",
]
# Multiple
res, status = await test_exec(
config,
"./addons/TechnoLibre_odoo-code-generator-template",
generated_module=",".join(lst_generated_module),
tested_module=",".join(lst_tested_module),
test_name="code_generator_data_part_2_test",
run_in_sandbox=True,
)
test_result += res
test_status += status
return test_result, test_status
async def run_code_generator_export_website_attachments_test(
config,
) -> Tuple[str, int]:
test_result = ""
test_status = 0
lst_generated_module = [
"demo_website_attachments_data",
]
lst_tested_module = [
"code_generator_demo_export_website_attachments",
]
# Multiple
res, status = await test_exec(
config,
"./addons/TechnoLibre_odoo-code-generator-template",
generated_module=",".join(lst_generated_module),
tested_module=",".join(lst_tested_module),
test_name="code_generator_export_website_attachments_test",
run_in_sandbox=True,
restore_db_image_name="test_website_attachments",
)
test_result += res
test_status += status
return test_result, test_status
async def run_code_generator_theme_test(config) -> Tuple[str, int]:
test_result = ""
test_status = 0
lst_generated_module = [
"theme_website_demo_code_generator",
]
lst_tested_module = [
"code_generator_demo_theme_website",
]
# Multiple
res, status = await test_exec(
config,
"./addons/TechnoLibre_odoo-code-generator-template",
generated_module=",".join(lst_generated_module),
tested_module=",".join(lst_tested_module),
test_name="code_generator_theme_test",
run_in_sandbox=True,
)
test_result += res
test_status += status
return test_result, test_status
async def run_code_generator_generic_all_test(config) -> Tuple[str, int]:
test_result = ""
test_status = 0
lst_generated_module = [
"demo_internal",
"demo_portal",
"demo_helpdesk_data",
"demo_website_data",
"demo_website_leaflet",
"demo_website_snippet",
"theme_website_demo_code_generator",
]
lst_tested_module = [
"code_generator_demo_internal",
"code_generator_demo_portal",
"code_generator_demo_export_helpdesk",
"code_generator_demo_export_website",
"code_generator_demo_website_leaflet",
"code_generator_demo_website_snippet",
"code_generator_demo_theme_website",
]
# Multiple
res, status = await test_exec(
config,
"./addons/TechnoLibre_odoo-code-generator-template",
generated_module=",".join(lst_generated_module),
tested_module=",".join(lst_tested_module),
test_name="code_generator_generic_all_test",
run_in_sandbox=True,
)
test_result += res
test_status += status
return test_result, test_status
async def run_code_generator_website_snippet_test(config) -> Tuple[str, int]:
test_result = ""
test_status = 0
lst_generated_module = [
"demo_website_leaflet",
"demo_website_snippet",
"demo_website_multiple_snippet",
]
lst_tested_module = [
"code_generator_demo_website_leaflet",
"code_generator_demo_website_snippet",
"code_generator_demo_website_multiple_snippet",
]
# Multiple
res, status = await test_exec(
config,
"./addons/TechnoLibre_odoo-code-generator-template",
generated_module=",".join(lst_generated_module),
tested_module=",".join(lst_tested_module),
test_name="code_generator_website_snippet_test",
run_in_sandbox=True,
)
test_result += res
test_status += status
if "code_generator_demo_website_multiple_snippet" in lst_tested_module:
# Because code_generator_demo_website_multiple_snippet depend on code_generator_demo_portal, it will
# execute it and this delete file demo_portal/i18n/demo_portal.pot and demo_portal/i18n/fr_CA.po
lst_file_is_delete = [
"demo_portal/i18n/demo_portal.pot",
"demo_portal/i18n/fr_CA.po",
]
path_to_check = os.path.join(
"addons", "TechnoLibre_odoo-code-generator-template"
)
repo_demo_portal = git.Repo(path_to_check)
status_to_check = repo_demo_portal.git.status("-s")
if all([f"D {a}" in status_to_check for a in lst_file_is_delete]):
# Revert it
for file_name in lst_file_is_delete:
repo_demo_portal.git.checkout(file_name)
else:
test_status += 1
test_result += (
f"\n\nFAIL - inspect to delete file ${lst_file_is_delete}"
) )
install_path = dct_test.get("install_path")
run_in_sandbox = dct_test.get("run_in_sandbox", True)
restore_db_image_name = dct_test.get(
"restore_db_image_name", "erplibre_base"
)
keep_cache = config.keep_cache
coverage = config.coverage
cb_coroutine = test_exec(
path_module_check,
generated_module=generated_module,
generate_path=generate_path,
tested_module=tested_module,
search_class_module=search_class_module,
script_after_init_check=script_after_init_check,
lst_init_module_name=lst_init_module_name,
file_to_restore=file_to_restore,
file_to_restore_origin=file_to_restore_origin,
test_name=test_name,
install_path=install_path,
run_in_sandbox=run_in_sandbox,
restore_db_image_name=restore_db_image_name,
keep_cache=keep_cache,
coverage=coverage,
)
if cb_coroutine:
dct_task[sequence].append(cb_coroutine)
dct_task_name[sequence].append(test_name)
lst_sequence = sorted(list(dct_task.keys()))
# Print summary
total_tpl_result = []
total_tpl_task = []
# Print summary
for sequence in lst_sequence:
lst_task = dct_task[sequence]
lst_task_name = dct_task_name[sequence]
print(f"sequence {sequence}")
lib_asyncio.print_summary_task(lst_task, lst_task_name=lst_task_name)
# Execute in sequence
for sequence in lst_sequence:
lst_task = dct_task[sequence]
tpl_result, has_asyncio_error = lib_asyncio.execute(config, lst_task)
if tpl_result:
total_tpl_result.extend(tpl_result)
else:
_logger.error("tpl_result is empty.")
if lst_task:
total_tpl_task.extend(lst_task)
else:
_logger.error("tpl_task is empty.")
return test_result, test_status print_log(total_tpl_task, total_tpl_result)
status = check_result(total_tpl_task, total_tpl_result)
async def run_code_generator_demo_generic_test(config) -> Tuple[str, int]:
test_result = ""
test_status = 0
lst_generated_module = [
"demo_internal",
"demo_portal",
]
lst_tested_module = [
"code_generator_demo_internal",
"code_generator_demo_portal",
]
# Multiple
res, status = await test_exec(
config,
"./addons/TechnoLibre_odoo-code-generator-template",
generated_module=",".join(lst_generated_module),
tested_module=",".join(lst_tested_module),
test_name="code_generator_demo_generic_test",
run_in_sandbox=True,
)
test_result += res
test_status += status
return test_result, test_status
async def run_code_generator_demo_test(config) -> Tuple[str, int]:
test_result = ""
test_status = 0
lst_generated_module = [
"code_generator_demo",
]
lst_tested_module = [
"code_generator_demo",
]
# Multiple
res, status = await test_exec(
config,
"./addons/TechnoLibre_odoo-code-generator-template",
generated_module=",".join(lst_generated_module),
tested_module=",".join(lst_tested_module),
test_name="code_generator_demo_test",
)
test_result += res
test_status += status
return test_result, test_status
async def run_code_generator_inherit_test(config) -> Tuple[str, int]:
# TODO can be merge into code_generator_multiple
test_result = ""
test_status = 0
lst_generated_module = [
"demo_internal_inherit",
]
lst_tested_module = [
"code_generator_demo_internal_inherit",
]
# Inherit
res, status = await test_exec(
config,
"./addons/TechnoLibre_odoo-code-generator-template",
generated_module=",".join(lst_generated_module),
tested_module=",".join(lst_tested_module),
test_name="code_generator_inherit_test",
run_in_sandbox=True,
)
test_result += res
test_status += status
return test_result, test_status
async def run_code_generator_auto_backup_test(config) -> Tuple[str, int]:
test_result = ""
test_status = 0
lst_generated_module = [
"auto_backup",
]
lst_tested_module = [
"code_generator_auto_backup",
]
# Auto-backup
res, status = await test_exec(
config,
"./addons/OCA_server-tools/auto_backup",
generated_module=",".join(lst_generated_module),
tested_module=",".join(lst_tested_module),
test_name="code_generator_auto_backup_test",
run_in_sandbox=True,
)
test_result += res
test_status += status
return test_result, test_status
async def run_code_generator_template_demo_portal_test(
config,
) -> Tuple[str, int]:
test_result = ""
test_status = 0
# Template
res, status = await test_exec(
config,
"./addons/TechnoLibre_odoo-code-generator-template",
generated_module="code_generator_demo_portal",
tested_module="code_generator_template_demo_portal",
search_class_module="demo_portal",
lst_init_module_name=[
"demo_portal",
],
test_name="code_generator_template_demo_portal",
run_in_sandbox=True,
)
test_result += res
test_status += status
return test_result, test_status
async def run_code_generator_template_demo_internal_test(
config,
) -> Tuple[str, int]:
test_result = ""
test_status = 0
# Template
res, status = await test_exec(
config,
"./addons/TechnoLibre_odoo-code-generator-template",
generated_module="code_generator_demo_internal",
tested_module="code_generator_template_demo_internal",
search_class_module="demo_internal",
lst_init_module_name=[
"demo_internal",
],
test_name="code_generator_template_demo_internal",
run_in_sandbox=True,
)
test_result += res
test_status += status
return test_result, test_status
async def run_code_generator_template_demo_internal_inherit_test(
config,
) -> Tuple[str, int]:
test_result = ""
test_status = 0
# Template
res, status = await test_exec(
config,
"./addons/TechnoLibre_odoo-code-generator-template",
generated_module="code_generator_demo_internal_inherit",
tested_module="code_generator_template_demo_internal_inherit",
search_class_module="demo_internal_inherit",
lst_init_module_name=[
"demo_internal_inherit",
],
test_name="code_generator_template_demo_internal_inherit",
run_in_sandbox=True,
)
test_result += res
test_status += status
return test_result, test_status
async def run_code_generator_template_demo_sysadmin_cron_test(
config,
) -> Tuple[str, int]:
test_result = ""
test_status = 0
# Template
res, status = await test_exec(
config,
"./addons/OCA_server-tools/auto_backup",
generated_module="code_generator_auto_backup",
generate_path="./addons/OCA_server-tools/",
tested_module="code_generator_template_demo_sysadmin_cron",
search_class_module="auto_backup",
lst_init_module_name=[
"auto_backup",
],
test_name="code_generator_template_demo_sysadmin_cron",
install_path="./addons/TechnoLibre_odoo-code-generator-template",
run_in_sandbox=True,
)
test_result += res
test_status += status
return test_result, test_status
async def run_helloworld_test(config) -> Tuple[str, int]:
res, status = await run_command(
"./test/code_generator/hello_world.sh", test_name="helloworld_test"
)
return res, status
def run_all_test(config) -> None:
# low in time, at the end for more speed
task_list = [
run_code_generator_migrator_demo_mariadb_sql_example_1_test(config),
run_code_generator_template_demo_mariadb_sql_example_1_test(config),
run_code_generator_demo_mariadb_sql_example_1_test(config),
run_code_generator_auto_backup_test(config),
run_code_generator_template_demo_portal_test(config),
run_code_generator_template_demo_internal_test(config),
run_code_generator_template_demo_internal_inherit_test(config),
run_code_generator_template_demo_sysadmin_cron_test(config),
run_code_generator_demo_test(config),
# Begin to run generic test
# run_code_generator_generic_all_test(config),
run_code_generator_data_test(config),
run_code_generator_data_test_part_2(config),
run_code_generator_export_website_attachments_test(config),
run_code_generator_theme_test(config),
run_code_generator_website_snippet_test(config),
run_code_generator_demo_generic_test(config),
# End run generic test
run_code_generator_inherit_test(config),
run_demo_test(config),
]
task_second_list = [
# TODO Will cause conflict with the other because write in code_generator_demo/hooks.py
run_helloworld_test(config),
]
_logger.info("First list task")
lib_asyncio.print_summary_task(task_list)
_logger.info("Second list task")
lib_asyncio.print_summary_task(task_second_list)
_logger.info("First execution")
tpl_result = lib_asyncio.execute(config, task_list)
_logger.info("Second execution")
tpl_result_second = lib_asyncio.execute(config, task_second_list)
# Extra
tpl_result_total = tpl_result + tpl_result_second
task_list_total = task_list + task_second_list
print_log(task_list_total, tpl_result_total)
status = check_result(task_list_total, tpl_result_total)
if status: if status:
log_file_print = LOG_FILE log_file_print = LOG_FILE
else: else:
log_file_print = f"{Fore.RED}{LOG_FILE}{Fore.RESET}" log_file_print = f"{Fore.RED}{LOG_FILE}{Style.RESET_ALL}"
if config.output_result_dir:
print_log_output_into_dir(total_tpl_result, config.output_result_dir)
print(f"Log file {log_file_print}") print(f"Log file {log_file_print}")
return status
def main(): def main():
@ -1250,14 +940,15 @@ def main():
success = check_git_change() success = check_git_change()
else: else:
success = True success = True
status = False
if success: if success:
run_all_test(config) status = run_all_test(config)
end_time = time.time() end_time = time.time()
diff_sec = end_time - start_time diff_sec = end_time - start_time
# print(f"Time execution {diff_sec:.3f}s") # print(f"Time execution {diff_sec:.3f}s")
print(f"Time execution {datetime.timedelta(seconds=diff_sec)}") print(f"Time execution {datetime.timedelta(seconds=diff_sec)}")
return 0 return int(not status)
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -1,20 +1,22 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Usage, ./test.sh -d test_addons_name -i module_name # Usage, ./test.sh -d test_addons_name -i module_name
source ./.venv/bin/activate source ./.venv/bin/activate
Red='\033[0;31m' # Red
Color_Off='\033[0m' # Text Reset
CONFIG_PATH="./config.conf" CONFIG_PATH="./config.conf"
ORIGIN_CONFIG_PATH=CONFIG_PATH ORIGIN_CONFIG_PATH=CONFIG_PATH
if [ ! -f "${CONFIG_PATH}" ]; then if [ ! -f "${CONFIG_PATH}" ]; then
CONFIG_PATH="/etc/odoo/odoo.conf" CONFIG_PATH="/etc/odoo/odoo.conf"
if [ ! -f "${CONFIG_PATH}" ]; then if [ ! -f "${CONFIG_PATH}" ]; then
echo "Cannot find ERPLibre configuration ${ORIGIN_CONFIG_PATH}, did you install ERPLibre? > make install" echo "${Red}Cannot find${Color_Off} ERPLibre configuration ${ORIGIN_CONFIG_PATH}, did you install ERPLibre? > make install"
exit 1 exit 1
fi fi
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 --stop-after-init "$@"
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "Error test.sh" echo "${Red}Error${Color_Off} run.sh"
exit 1 exit 1
fi fi