Merge branch 'develop'

- improve selenium windows size
- update license
- fix pycharm_configuration about multi version odoo
- update dependency
- downgrade postgresql 18 to 17
cause a problem with some database restoration
- format support multiple repo and file with space
- fix repo clean all
- more adaptation for odoo 18, like the code generator
This commit is contained in:
Mathieu Benoit 2025-11-08 23:53:21 -05:00
commit fad04b59ee
67 changed files with 904 additions and 531 deletions

View file

@ -32,6 +32,7 @@ endif
# Include all Makefile
-include ./conf/make.code_generator.Makefile
-include ./conf/make.robotlibre.Makefile
-include ./conf/make.erplibre.Makefile
-include ./conf/make.database.Makefile
-include ./conf/make.docker.Makefile

View file

@ -0,0 +1,121 @@
#########
# Robot #
#########
.PHONY: robot_libre_all
robot_libre_all:
echo "Install all for robot_libre"
./script/make.sh robot_libre_init
./script/make.sh robot_libre_pre
OPEN_DASHBOARD=TRUE ./run.sh --dev cg -d robotlibre -i erplibre_devops,erplibre_devops_me,erplibre_devops_extra
.PHONY: robot_libre_init
robot_libre_init:
echo "Robot Libre init"
echo "Sorry for your lost data"
echo "Generate repository"
#./script/manifest/update_manifest_local_dev.sh "-g base,image_db,code_generator"
echo "Generate new fast configuration repo"
#./script/git/git_repo_update_group.py --group base,code_generator
echo "Generate configuration"
#./script/generate_config.sh
#./script/git/git_change_remote_https_to_git.py
.PHONY: robot_libre_pre
robot_libre_pre:
echo "Create database robotlibre"
./script/database/db_restore.py --database robotlibre
.PHONY: robot_libre
robot_libre:
./script/make.sh robot_libre_pre
echo "Install devops"
./script/addons/install_addons_dev.sh robotlibre erplibre_devops
./odoo_bin.sh db --backup --database robotlibre --restore_image robotlibre_last
.PHONY: robot_libre_fast
robot_libre_fast:
echo "FAST! RobotLibre"
./odoo_bin.sh db --drop --database _cache_robotlibre_last
./script/database/db_restore.py --database robotlibre --image robotlibre_last
.PHONY: robot_libre_fast_update
robot_libre_fast_update:
echo "FAST! RobotLibre with update"
./odoo_bin.sh db --drop --database _cache_robotlibre_last
./script/database/db_restore.py --database robotlibre --image robotlibre_last
./script/addons/install_addons_dev.sh robotlibre erplibre_devops
.PHONY: robot_libre_extra
robot_libre_extra:
./script/make.sh robot_libre_pre
echo "Install erplibre_devops and erplibre_devops_extra"
./script/addons/install_addons_dev.sh robotlibre erplibre_devops,erplibre_devops_extra
./odoo_bin.sh db --backup --database robotlibre --restore_image robotlibre_last
.PHONY: robot_libre_me
robot_libre_me:
./script/make.sh robot_libre_pre
echo "Install erplibre_devops, erplibre_devops_me and erplibre_devops_extra"
OPEN_DASHBOARD=TRUE ./run.sh --dev cg -d robotlibre -i erplibre_devops,erplibre_devops_me,erplibre_devops_extra
./odoo_bin.sh db --backup --database robotlibre --restore_image robotlibre_last
.PHONY: robot_libre_me_only
robot_libre_me_only:
./script/make.sh robot_libre
IS_ONLY_ME=TRUE ./run.sh --dev cg -d robotlibre -i erplibre_devops_me
./odoo_bin.sh db --backup --database robotlibre --restore_image robotlibre_last
.PHONY: robot_libre_me_auto
robot_libre_me_auto:
./script/make.sh robot_libre
IS_ME_AUTO=TRUE ./run.sh --dev cg -d robotlibre -i erplibre_devops_me
.PHONY: robot_libre_me_auto_force
robot_libre_me_auto_force:
./script/make.sh robot_libre
IS_ME_AUTO_FORCE=TRUE ./run.sh --dev cg -d robotlibre -i erplibre_devops_me
.PHONY: robot_libre_me_only_auto_force
robot_libre_me_only_auto_force:
./script/make.sh robot_libre
IS_ONLY_ME=TRUE IS_ME_AUTO_FORCE=TRUE ./run.sh --dev cg -d robotlibre -i erplibre_devops_me
.PHONY: robot_libre_update
robot_libre_update:
./run.sh --limit-time-real 999999 --no-http --stop-after-init --dev cg -d robotlibre -i erplibre_devops -u erplibre_devops
.PHONY: robot_libre_run
robot_libre_run:
./run.sh -d robotlibre
.PHONY: robot_libre_open
robot_libre_open:
source .venv.erplibre/bin/activate;python ./script/selenium/web_login.py
.PHONY: robot_libre_open_record
robot_libre_open_record:
source .venv.erplibre/bin/activate;python ./script/selenium/web_login.py --record_mode
.PHONY: robot_libre_format
robot_libre_format:
parallel ::: "./script/maintenance/format.sh ./addons/ERPLibre_erplibre_addons/erplibre_devops" "./script/maintenance/format.sh ./addons/ERPLibre_erplibre_addons/erplibre_devops_me"
.PHONY: robot_libre_generate
robot_libre_generate:
./script/code_generator/new_project.py -f -d ./addons/ERPLibre_erplibre_addons -m erplibre_devops
.PHONY: run_db
run_db:
./run.sh -d $(bd)
.PHONY: robot_libre_selenium_generate_code_example_01
robot_libre_selenium_generate_code_example_01:
source .venv.erplibre/bin/activate;python ./script/selenium/scenario/selenium_devops.py --open_me_devops --generate_code
.PHONY: robot_libre_selenium_generate_code_example_01_record
robot_libre_selenium_generate_code_example_01_record:
source .venv.erplibre/bin/activate;python ./script/selenium/scenario/selenium_devops.py --open_me_devops --generate_code --not_private_mode --video_suffix not_private_mode --no_dark_mode --record_mode --window_size 1920,1080
.PHONY: robot_libre_selenium_generate_code_example_01_record_cell
robot_libre_selenium_generate_code_example_01_record_cell:
source .venv.erplibre/bin/activate;python ./script/selenium/scenario/selenium_devops.py --open_me_devops --generate_code --not_private_mode --video_suffix not_private_mode --no_dark_mode --record_mode --window_size 1080,1920

View file

@ -1,6 +1,7 @@
name,script_path,parameters,folder,default
run,./odoo/odoo-bin,--limit-time-real 999999 -c config.conf,run,True
run_parallel_test,./script/test/run_parallel_test.py,,test,
robotlibre_devops_update,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d robotlibre -u erplibre_devops,devops,
cg_cg,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_code_generator,code_generator,
cg_cg_template,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_code_generator,code_generator_template,
code_generator_auto_backup,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_auto_backup,code_generator,

1 name script_path parameters folder default
2 run ./odoo/odoo-bin --limit-time-real 999999 -c config.conf run True
3 run_parallel_test ./script/test/run_parallel_test.py test
4 robotlibre_devops_update ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d robotlibre -u erplibre_devops devops
5 cg_cg ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_code_generator code_generator
6 cg_cg_template ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_code_generator code_generator_template
7 code_generator_auto_backup ./odoo/odoo-bin --limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_auto_backup code_generator

View file

@ -32,14 +32,14 @@ services:
restart: always
db:
image: postgis/postgis:18-3.6-alpine
image: postgis/postgis:17-3.6-alpine
environment:
POSTGRES_PASSWORD: mysecretpassword
POSTGRES_USER: odoo
POSTGRES_DB: postgres
PGDATA: /var/lib/postgresql/pgdata
PGDATA: /var/lib/postgresql/data/pgdata
volumes:
- erplibre-db-data:/var/lib/postgresql/pgdata
- erplibre-db-data:/var/lib/postgresql/data/pgdata
restart: always
# We configure volume without specific destination to let docker manage it. To configure it through docker use (read related documentation before continuing) :

View file

@ -33,14 +33,14 @@ services:
restart: always
db:
image: postgis/postgis:18-3.6-alpine
image: postgis/postgis:17-3.6-alpine
environment:
POSTGRES_PASSWORD: mysecretpassword
POSTGRES_USER: odoo
POSTGRES_DB: postgres
PGDATA: /var/lib/postgresql/pgdata
PGDATA: /var/lib/postgresql/data/pgdata
volumes:
- erplibre-db-data:/var/lib/postgresql/pgdata
- erplibre-db-data:/var/lib/postgresql/data/pgdata
restart: always
# We configure volume without specific destination to let docker manage it. To configure it through docker use (read related documentation before continuing) :

View file

@ -34,14 +34,14 @@ services:
restart: always
db:
image: postgis/postgis:18-3.6-alpine
image: postgis/postgis:17-3.6-alpine
environment:
POSTGRES_PASSWORD: mysecretpassword
POSTGRES_USER: odoo
POSTGRES_DB: postgres
PGDATA: /var/lib/postgresql/pgdata
PGDATA: /var/lib/postgresql/data/pgdata
volumes:
- erplibre-db-data:/var/lib/postgresql/pgdata
- erplibre-db-data:/var/lib/postgresql/data/pgdata
restart: always
chrome:

View file

@ -1,29 +1,34 @@
#!/usr/bin/env python
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse
from os import listdir
from os.path import isdir, join, abspath
import configparser
from os import listdir
from os.path import abspath, isdir, join
parser = argparse.ArgumentParser(prog='Configure base dir for all addons')
parser = argparse.ArgumentParser(prog="Configure base dir for all addons")
parser.add_argument("addonsBaseDir", help="Path where addons are cloned.")
parser.add_argument("srcConfigPath",
help="Path where we retrieve source config file to adapt with new "
"addons path.")
parser.add_argument("dstConfigPath", help="Path to save adapted configuration.")
parser.add_argument(
"srcConfigPath",
help="Path where we retrieve source config file to adapt with new "
"addons path.",
)
parser.add_argument(
"dstConfigPath", help="Path to save adapted configuration."
)
args = parser.parse_args()
addonsBaseDir = args.addonsBaseDir
srcConfigPath = args.srcConfigPath
dstConfigPath = args.dstConfigPath
addonsDirs = [abspath(join(addonsBaseDir, f)) for f in listdir(addonsBaseDir) if
isdir(join(addonsBaseDir, f))]
addonsDirs = [
abspath(join(addonsBaseDir, f))
for f in listdir(addonsBaseDir)
if isdir(join(addonsBaseDir, f))
]
with open(".odoo-version", "r") as f:
odoo_version = f.readline().strip()
@ -39,9 +44,9 @@ config.read(srcConfigPath)
separator = ","
config.set('options', 'addons_path', separator.join(addonsDirs))
config.set("options", "addons_path", separator.join(addonsDirs))
print(config.get('options', 'addons_path'))
print(config.get("options", "addons_path"))
with open(dstConfigPath, 'w') as configfile:
with open(dstConfigPath, "w") as configfile:
config.write(configfile)

View file

@ -1,20 +1,21 @@
#!/usr/bin/env python
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse
import psycopg2
import sys
import time
if __name__ == '__main__':
import psycopg2
if __name__ == "__main__":
arg_parser = argparse.ArgumentParser()
arg_parser.add_argument('--db_host', required=True)
arg_parser.add_argument('--db_port', required=True)
arg_parser.add_argument('--db_user', required=True)
arg_parser.add_argument('--db_password', required=True)
arg_parser.add_argument('--db_name', required=False, default="postgres")
arg_parser.add_argument('--timeout', type=int, default=10)
arg_parser.add_argument("--db_host", required=True)
arg_parser.add_argument("--db_port", required=True)
arg_parser.add_argument("--db_user", required=True)
arg_parser.add_argument("--db_password", required=True)
arg_parser.add_argument("--db_name", required=False, default="postgres")
arg_parser.add_argument("--timeout", type=int, default=10)
args = arg_parser.parse_args()
@ -22,12 +23,16 @@ if __name__ == '__main__':
print("Try connection to postgres...")
connected = False
error = ''
error = ""
while ((time.time() - start_time) < args.timeout) or connected is True:
try:
conn = psycopg2.connect(user=args.db_user, host=args.db_host,
port=args.db_port, password=args.db_password,
dbname=args.db_name)
conn = psycopg2.connect(
user=args.db_user,
host=args.db_host,
port=args.db_port,
password=args.db_password,
dbname=args.db_name,
)
break
except psycopg2.OperationalError as e:
error = e

View file

@ -325,7 +325,7 @@
name="erplibre_addons.git"
path="odoo12.0/addons/ERPLibre_erplibre_addons"
remote="ERPLibre"
revision="12.0_erplibre_devops"
revision="12.0"
groups="addons,odoo12.0,base"
/>
<project

View file

@ -236,10 +236,14 @@ description = "Read/rewrite/write Python ASTs"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7"
groups = ["main"]
files = [
{file = "astor-0.8.1-py2.py3-none-any.whl", hash = "sha256:070a54e890cefb5b3739d19f30f5a5ec840ffc9c50ffa7d23cc9fc1a38ebbfc5"},
{file = "astor-0.8.1.tar.gz", hash = "sha256:6a6effda93f4e1ce9f618779b2dd1d9d84f1e32812c23a29b3fff6fd7f63fa5e"},
]
files = []
develop = false
[package.source]
type = "git"
url = "https://github.com/berkerpeksag/astor.git"
reference = "HEAD"
resolved_reference = "df09001112f079db54e7c5358fa143e1e63e74c4"
[[package]]
name = "astroid"
@ -503,18 +507,18 @@ xyzservices = ">=2021.09.1"
[[package]]
name = "boto3"
version = "1.40.64"
version = "1.40.67"
description = "The AWS SDK for Python"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "boto3-1.40.64-py3-none-any.whl", hash = "sha256:35ca3dd80dd90d5f4e8ed032440f28790696fdf50f48c0d16a09a75675f9112f"},
{file = "boto3-1.40.64.tar.gz", hash = "sha256:b92d6961c352f2bb8710c9892557d4b0e11258b70967d4e740e1c97375bcd779"},
{file = "boto3-1.40.67-py3-none-any.whl", hash = "sha256:3d06e9b3c7abedb8253c7d75b9ab27005480ca1e6e448d1f3c3cc3e209673ca0"},
{file = "boto3-1.40.67.tar.gz", hash = "sha256:3e4317139ace6d44658b8e1f2b5b6612f05b45720721841c90cdee45b02aa514"},
]
[package.dependencies]
botocore = ">=1.40.64,<1.41.0"
botocore = ">=1.40.67,<1.41.0"
jmespath = ">=0.7.1,<2.0.0"
s3transfer = ">=0.14.0,<0.15.0"
@ -523,14 +527,14 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"]
[[package]]
name = "botocore"
version = "1.40.64"
version = "1.40.67"
description = "Low-level, data-driven core of boto 3."
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "botocore-1.40.64-py3-none-any.whl", hash = "sha256:6902b3dadfba1fbacc9648171bef3942530d8f823ff2bdb0e585a332323f89fc"},
{file = "botocore-1.40.64.tar.gz", hash = "sha256:a13af4009f6912eafe32108f6fa584fb26e24375149836c2bcaaaaec9a7a9e58"},
{file = "botocore-1.40.67-py3-none-any.whl", hash = "sha256:e49e61f6718e8bc8b34e9bb8a97f16c8dc560485faef4981b55d76f825c9d78a"},
{file = "botocore-1.40.67.tar.gz", hash = "sha256:cc086f39c877aee0ea8dc88ef69062c9f395b9d30d49bfcfac7b8b7e61864b3a"},
]
[package.dependencies]
@ -1241,84 +1245,51 @@ tests = ["pytest", "pytest-cov", "pytest-xdist"]
[[package]]
name = "cython"
version = "3.1.6"
version = "3.2.0"
description = "The Cython compiler for writing C extensions in the Python language."
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
{file = "cython-3.1.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c4027b4d1bf7781fdfb2dbe1c1d81ccac9b910831511747e2c9fc8452fb3ea6b"},
{file = "cython-3.1.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:141dea9df09f9c711af3b95510bd417c58b2abd33676eef1cb61f25581f7090a"},
{file = "cython-3.1.6-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:486376a988268408b7e8ea7b4cccffb914aa497c498b41589fb4a862ba47e050"},
{file = "cython-3.1.6-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bdc6e63a04ead11812752a5198b85b7fc079688c76712348d072403f18fdeb49"},
{file = "cython-3.1.6-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:47e79f0bfbf403a5d6008bc9e7214e81e647794ca95cae6716399ba21abcc706"},
{file = "cython-3.1.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2379f729f1d5a445adb4621f279f7c23aeb6245f036f96cce14b5b2fd1f5ff0a"},
{file = "cython-3.1.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1089e18d938b6e742f077e398d52e1701080213c4f203755afde6f1b33d9e051"},
{file = "cython-3.1.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:73576246abbc62397db85cbdde74d2e5d73dabfdb7e593fdbb3671275ffb50ce"},
{file = "cython-3.1.6-cp310-cp310-win32.whl", hash = "sha256:f48eae3275b3352ba7eb550fc5321b0fb1ba8d916fa9985fb2f02ce42ae69ddd"},
{file = "cython-3.1.6-cp310-cp310-win_amd64.whl", hash = "sha256:4066908ee24a18572880966de1d0865d178f5ab9828a9249faa97e1ffdfbed9f"},
{file = "cython-3.1.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5a1aedd8990f470d108b76ca768d9f1766d6610cf2546b73075dbe1e523daebe"},
{file = "cython-3.1.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f75c33e83e224737b1a68b2868bc08bddaabc6f04aef74864ff6069fe2e68341"},
{file = "cython-3.1.6-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:91b8fb3e961b3344bf257b851f2ce679727f44857fec94d643bcc458601dab54"},
{file = "cython-3.1.6-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1cfeb04d43464f5ff8398b499ba46c6eef22093da0e74b25f972576e768880e7"},
{file = "cython-3.1.6-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f32366c198ac663a540ff4fa6ed55801d113183616c51100f4cc533568d2c4cf"},
{file = "cython-3.1.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9856e8cd7f7a95a3f10a8f15fef4d17e5a4a57fb5185fe3482cec4adb0536635"},
{file = "cython-3.1.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6966f4d4ee13eceade2d952dc63bdf313f413c0c3f165aef0d6f62e6f27dab02"},
{file = "cython-3.1.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dffb14bc986626be50003f4edc614a2c0a56cbaaf87259f6c763a6d21da14921"},
{file = "cython-3.1.6-cp311-cp311-win32.whl", hash = "sha256:cde4748d37483b6c91df9f4327768e2828b1e374cb61bcee06d618958de59b7b"},
{file = "cython-3.1.6-cp311-cp311-win_amd64.whl", hash = "sha256:29d6141b0c9697dfcaf5940eceb06353bec76f51f0579658964c0d29418000df"},
{file = "cython-3.1.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0d2c32e8f6c65854e8203b381ff7ab540820763756b7c326e2c8dc18c9bbb44e"},
{file = "cython-3.1.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:be24fcde7300a81712af279467ebc79baafc8483eb4dfa4daebf8ee90a826d39"},
{file = "cython-3.1.6-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5012025af433bd7188fe1f7705df1c4a67e7add80c71658f6c6bc35ea876cc68"},
{file = "cython-3.1.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3b3520e2d4484f927c3ec00d32ffda75ec72cfd6a2ee07adac721cce339fa26f"},
{file = "cython-3.1.6-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c8a01d241d775319bcd7adb4144b070e1c4b01cdf841a62032492f07fad9efdc"},
{file = "cython-3.1.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:fd88799fa7bb177182423e0745c9197c50938c6839ebfbe6fd01539582ed488e"},
{file = "cython-3.1.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:f809bae2e00b79c01ff5daf9a260df7c1bc9fda087b9d625592fa28c1a2248a9"},
{file = "cython-3.1.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6f657e7a4b2242d159de603f280928d8e458dfba48144714774ad76c08f5a530"},
{file = "cython-3.1.6-cp312-cp312-win32.whl", hash = "sha256:6502f3e58db0ab3e2c983bec2c8c9e45d602e2c7ff921a5a8515b0008d918102"},
{file = "cython-3.1.6-cp312-cp312-win_amd64.whl", hash = "sha256:71d099d8d6094c5de63a32e67b29964565aed889a218e8d16a94083f4239b904"},
{file = "cython-3.1.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:14f0d6b9f803eacf48e9e80ea12a03f54e5f5ac48914341b0a6b81554b3b3154"},
{file = "cython-3.1.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ec79615d0e29fa29fd4283bc7a2ed9c3d00532086a0031532d64b724db8c3e8e"},
{file = "cython-3.1.6-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:037d457738cf4fc12260946c6524b745f488cf413428099f2a064af7612d181f"},
{file = "cython-3.1.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b036cb4ed7abcbc89cc04311832b22ad386c532fdd1fe690e1364aa992a54c7"},
{file = "cython-3.1.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e0fb2694327834c5bda7c5a07605f76437354d0ff76bb8739e77b479d176cf52"},
{file = "cython-3.1.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92eb7a39e60426165a5b2a219af181e5695c4dedd598e317a7a4d9086bd66b91"},
{file = "cython-3.1.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c475018b28f4e7111148bd02b600595090e0aac6cc49615c4586bb4e7f164a22"},
{file = "cython-3.1.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b1b4bb661103cb95c6ca70daf5d39992b2d89fd260b02a54d92e365095ed37eb"},
{file = "cython-3.1.6-cp313-cp313-win32.whl", hash = "sha256:69b1bea23b51628b8c9f14c3e0bb4c7dd5be63781bfbaa581b1c683b473c728a"},
{file = "cython-3.1.6-cp313-cp313-win_amd64.whl", hash = "sha256:c844004712a9fe2a6f2ed4d6fe02aabb2e0e34f88c150724aad1afec7caff37a"},
{file = "cython-3.1.6-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:8893619efa77fc83934c1255c619d522711a5cf5933cef0d5c2b9755e8e5fabc"},
{file = "cython-3.1.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:bb49c74220af0b098f406701f0b87876b1c7614716d39786306986b9feea774b"},
{file = "cython-3.1.6-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:defbf9571fca78e8a6e21b93d35c0a491d6af77a8e6180a0146da1b3c8eb8ce6"},
{file = "cython-3.1.6-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cd7ea8c6ce0adf52d142bf37c4d54b8d0356818144a4584a24f2a0b9cdae6b8"},
{file = "cython-3.1.6-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c47fcc47553214e0a139fd33199d825c5d13970cd6c1039d2594af855ffb338"},
{file = "cython-3.1.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:92489385bca6d1935913540e35701a979618fdfeed4dbec6cad1be924fb487bf"},
{file = "cython-3.1.6-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:926a3efd9b7012cdb3df0d1886e6f0e32e0b72a5d311ac2d3f48c0716fd91c6d"},
{file = "cython-3.1.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e35118eedfa0138154a43fb6b14e83703dae93193ba9940c747c170ed845cca7"},
{file = "cython-3.1.6-cp314-cp314-win32.whl", hash = "sha256:27f2b26442737d6e080900284883e078aae0276dfd7715a49b338f1a9481f7b9"},
{file = "cython-3.1.6-cp314-cp314-win_amd64.whl", hash = "sha256:7f75ead2a7cad5ee719427b915711c70e40a114f045b2a9b5bd983484a0b83a7"},
{file = "cython-3.1.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9fdc17c4b0b1b5fba32880b718b89062e001b65695939a3db27586f0b6d0199e"},
{file = "cython-3.1.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8a1b288238f4e33dbb51cf7263582821cc57f98a78d1ede6e64fab424969503c"},
{file = "cython-3.1.6-cp38-cp38-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a0e3a2b307c6e48e1a9ad12ca487906f8783b5473157bd4563b680e85949b3bf"},
{file = "cython-3.1.6-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:81e6fe7eb6bb902fc86b97672f284a5c04c9c5f14e2466fb65e6ee68a27dbff7"},
{file = "cython-3.1.6-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a1059d0f5b5cf654c280721e6d07b8b2dfd104b3b8336449dc41e1abf6f09392"},
{file = "cython-3.1.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:48e7dba361cc6ffaf90623e20a7a663bc19e9a24bcfdabbe87deef4d816abedb"},
{file = "cython-3.1.6-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:162d4207e79894b2094c7152192a40aa0782c9d61b4c5e6fe087a1c4c1d5eb41"},
{file = "cython-3.1.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:f04b5b7e594ae7a43fe17812f8ab1a3b76b69e487c338b71f0def6edaa4c851d"},
{file = "cython-3.1.6-cp38-cp38-win32.whl", hash = "sha256:206f44565f9fbb3806c0b7cd7184944ab1e9f53a367a657dd459140fa37ef858"},
{file = "cython-3.1.6-cp38-cp38-win_amd64.whl", hash = "sha256:ca1ae069ed8ba89343e55513f541ac06674d5888e218ec3bb08810c2dfe53024"},
{file = "cython-3.1.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f91791319fff49e41acee86f7933e3f2c186610898b899d3dbf209dfcffa1ccd"},
{file = "cython-3.1.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2375531527162296fef6c2b4db6801a704a164235d6981098381a76defe1ed46"},
{file = "cython-3.1.6-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5ca38c150c486025d937cdf5c82830eea1c69d9f1ab9b34e877365f96c73a63d"},
{file = "cython-3.1.6-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f8dd368ec73dbed6f3022d03a37d1ed23285b1e41f736da6f34cb8fc14892bfb"},
{file = "cython-3.1.6-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7735d1b301a99a85a20758cddd9d66a33b36c225efe9de0e17c0abd998f2f32"},
{file = "cython-3.1.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6c19cbfb3adcbec754742e9fd096cdb8537e9f7dabcf376c78e02d145ec30c99"},
{file = "cython-3.1.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:958cb56acced5faf22c9ec8eace122b9ee7e591b089ee1dcf0ed1b4511122653"},
{file = "cython-3.1.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:07f8231e45cfedbfbd384c9bcab5c09ebead662ecf4fdf7983e3dc1625a09b13"},
{file = "cython-3.1.6-cp39-cp39-win32.whl", hash = "sha256:0d28b3f7c580f0a59b4e46524094f7d0a231eb19f679a27bcfc3b13c0599fc88"},
{file = "cython-3.1.6-cp39-cp39-win_amd64.whl", hash = "sha256:ea8e5e190b0aa628e0cfabd3200453fdbe8efc7ee5a7eef409c4e5a0975d9b57"},
{file = "cython-3.1.6-py3-none-any.whl", hash = "sha256:91dcf7eb9b6a089ce4e9e1140e571d84c3bca834afb77ec269be7aa9d31a8157"},
{file = "cython-3.1.6.tar.gz", hash = "sha256:ff4ccffcf98f30ab5723fc45a39c0548a3f6ab14f01d73930c5bfaea455ff01c"},
{file = "cython-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ee408125b2d218ec7d7a061e09d24715fcab9bf7ea1a4ac01907c3f8ec8730b3"},
{file = "cython-3.2.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c93ce307b05fcd86a5bb0e4a7d7fab238e2f0e9936636097a60bc0e21f2def30"},
{file = "cython-3.2.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:191cfc2fa84642ad41a52d5abaacfb330d9a6653a465e4bf0a5681f66197a967"},
{file = "cython-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:a259053037ef82959b743b7fde238bd191ee43f88eb8e51101d5f3d8849f1e32"},
{file = "cython-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e9e4b2248dc3a98b86aeba65e9862d2cc881d072c163c0fb31b511d4d72e93c8"},
{file = "cython-3.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:02fb4990a83d5d6f780dda18ed8baa8d587cb6523f57b4d72bc0b41ad3766c96"},
{file = "cython-3.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8a98925517819d62ea25d2cf40057df60a9bcf75fdd1d6ed3882e6ae0730d82f"},
{file = "cython-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:4c959a5d4cd6331e8498822ba47200bd2ff4bf74517c0c91475d5bc21da3b4d5"},
{file = "cython-3.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:511d823d9f8a1b850178ec355d6df0a1731b9c20b08ee6d1a780f68215e9013f"},
{file = "cython-3.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bbadeedcb2d135655bcce7380fb28c9e2a75b6810426c12b6e5a6fe6106fafb4"},
{file = "cython-3.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:92d2394a3e3fe704210b5324eb8118333b514af72c98b1e02a6503945825b231"},
{file = "cython-3.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:73435e56654a34ece57d4c3304a4556a8402cc4ae2d0e30f71c237a985dc5246"},
{file = "cython-3.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d900e58e826f9a5a27b0e2b50e33473e9986a5bae375c39b0f2e19f2c545fa23"},
{file = "cython-3.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a9d38cd3aab720d21fa6d6ee168228352f69aea0a95bd4fb84e8879c6ed38fbb"},
{file = "cython-3.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:92b31d0b7b0a49b3d2aa94faaf75d44a03174cff2616b341a8853c919e511d51"},
{file = "cython-3.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:2847b74e76dbad612f6fc7182c12a5f78cffb0d05808fd2c4b638cf02d1aade6"},
{file = "cython-3.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a0a8274959d538d12f865193dcd67bb5630906e020190c890d2b7c13d31713c6"},
{file = "cython-3.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a1c800833c25195833805c7c3626a2c30b3baaaa9ba361a1af3bbc379662a8d"},
{file = "cython-3.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:df15af08c21c18a2e848df5954d6fd3310735089b60405132fa4111e2cf7482a"},
{file = "cython-3.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:9d6876af2132757fff1b42a2f4eaa72482f991863160e3f0dc8f2c812b300ebf"},
{file = "cython-3.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d41c8c3d4a98f151ec11b80e5aa865fce0cec2b5c7f49ed477e06d6aa03fe17c"},
{file = "cython-3.2.0-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:acc01538767f9bd467494860f0ec0644d6f6ba5bd768b7f14d7b404a459b19fa"},
{file = "cython-3.2.0-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f237b1fa3d1c527a0f848d527b3013dd6f89ef2ab3907d79dd84415465fd755d"},
{file = "cython-3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:b8461df22d8ea1233eceeaf329d359c8870023f48515209eb0b79902583f7207"},
{file = "cython-3.2.0-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:04821ce06598a3aa5c9e0270d98960cfe6556dedbd1418c65e4479162b8ae74a"},
{file = "cython-3.2.0-cp39-abi3-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:54b5b1c72a63da822b3f4739a0e31546c0a19f8e834b174906bf817ed5f9d65f"},
{file = "cython-3.2.0-cp39-abi3-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6155a6c360e32af1aaa16fa10b0119b49deeadff42a1958973324150870af1b5"},
{file = "cython-3.2.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:861258ac3878b76c57b9b5a379787d772a0bc47fec9167b43986777de542c474"},
{file = "cython-3.2.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:85dbf955e3193893d0288105afa0fa5f4e835ff587061681f240a4f0487c44fb"},
{file = "cython-3.2.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:3b3f13822526726bac43275c0e92916bbcc2c30e9f559edc4c1132670b70498d"},
{file = "cython-3.2.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ab18d09673d219008be5b6174bcbb6dbfd50904e66371f104a8a4698b791472d"},
{file = "cython-3.2.0-cp39-abi3-win32.whl", hash = "sha256:c9fd986413fc52929b916187630a9abab9f876299951488c4b905ad5346afee6"},
{file = "cython-3.2.0-cp39-abi3-win_arm64.whl", hash = "sha256:ee2ea79ddeb721f912e7efea039b9db059c81767ff04fbf9a995f64e1187df99"},
{file = "cython-3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b6e5df85f6dca0ccad0d86f7517d70653d74fcd9e739fc5eb8fb23312f07b73d"},
{file = "cython-3.2.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eba59b55e9d743b5b62a57cef942688c1f52e09632ea6f25b3bbe6c47ecc2db2"},
{file = "cython-3.2.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fdc6f4a34af5122490b154eb2878b6377b36844e42476c42472dfe5afbac7533"},
{file = "cython-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:9b54abd3dfd2bf43fdcba1a27fcfe1012a4b196ab77d7fd20fb97942d1ac0ed5"},
{file = "cython-3.2.0-py3-none-any.whl", hash = "sha256:73f7f4c75acde5b5b4df05b11fdc2705ec637b99241d1bc2f4ebf345f7a2ea90"},
{file = "cython-3.2.0.tar.gz", hash = "sha256:41fdce8237baee2d961c292ed0386903dfe126f131e450a62de0fd7a5280d4b2"},
]
[[package]]
@ -2470,22 +2441,20 @@ files = [
[[package]]
name = "img2pdf"
version = "0.6.1"
description = "Convert images to PDF via direct JPEG inclusion."
version = "0.6.3"
description = "Lossless conversion of raster images to PDF."
optional = false
python-versions = "*"
python-versions = ">=3.5"
groups = ["main"]
files = [
{file = "img2pdf-0.6.1.tar.gz", hash = "sha256:306e279eb832bc159d7d6294b697a9fbd11b4be1f799b14b3b2174fb506af289"},
{file = "img2pdf-0.6.3-py3-none-any.whl", hash = "sha256:44d12d235752edd17c43c04ff39952cdc5dd4c6aba90569c4902bd445085266b"},
{file = "img2pdf-0.6.3.tar.gz", hash = "sha256:219518020f5bd242bdc46493941ea3f756f664c2e86f2454721e74353f58cd95"},
]
[package.dependencies]
pikepdf = "*"
Pillow = "*"
[package.extras]
gui = ["tkinter"]
[[package]]
name = "iso3166"
version = "2.1.1"
@ -3696,6 +3665,31 @@ files = [
{file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"},
]
[[package]]
name = "narwhals"
version = "2.10.2"
description = "Extremely lightweight compatibility layer between dataframe libraries"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "narwhals-2.10.2-py3-none-any.whl", hash = "sha256:059cd5c6751161b97baedcaf17a514c972af6a70f36a89af17de1a0caf519c43"},
{file = "narwhals-2.10.2.tar.gz", hash = "sha256:ff738a08bc993cbb792266bec15346c1d85cc68fdfe82a23283c3713f78bd354"},
]
[package.extras]
cudf = ["cudf (>=24.10.0)"]
dask = ["dask[dataframe] (>=2024.8)"]
duckdb = ["duckdb (>=1.1)"]
ibis = ["ibis-framework (>=6.0.0)", "packaging", "pyarrow-hotfix", "rich"]
modin = ["modin"]
pandas = ["pandas (>=1.1.3)"]
polars = ["polars (>=0.20.4)"]
pyarrow = ["pyarrow (>=13.0.0)"]
pyspark = ["pyspark (>=3.5.0)"]
pyspark-connect = ["pyspark[connect] (>=3.5.0)"]
sqlframe = ["sqlframe (>=3.22.0,!=3.39.3)"]
[[package]]
name = "nextcloud-api-wrapper"
version = "0.2.3"
@ -3932,14 +3926,14 @@ full = ["XLMMacroDeobfuscator"]
[[package]]
name = "openai"
version = "2.6.1"
version = "2.7.1"
description = "The official Python library for the openai API"
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
{file = "openai-2.6.1-py3-none-any.whl", hash = "sha256:904e4b5254a8416746a2f05649594fa41b19d799843cd134dac86167e094edef"},
{file = "openai-2.6.1.tar.gz", hash = "sha256:27ae704d190615fca0c0fc2b796a38f8b5879645a3a52c9c453b23f97141bb49"},
{file = "openai-2.7.1-py3-none-any.whl", hash = "sha256:2f2530354d94c59c614645a4662b9dab0a5b881c5cd767a8587398feac0c9021"},
{file = "openai-2.7.1.tar.gz", hash = "sha256:df4d4a3622b2df3475ead8eb0fbb3c27fd1c070fa2e55d778ca4f40e0186c726"},
]
[package.dependencies]
@ -3975,14 +3969,14 @@ et-xmlfile = "*"
[[package]]
name = "openupgradelib"
version = "3.11.1"
version = "3.12.0"
description = "A library with support functions to be called from Odoo migration scripts."
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
groups = ["main"]
files = [
{file = "openupgradelib-3.11.1-py2.py3-none-any.whl", hash = "sha256:e34c57c835e6434171ceebe00d4a6b3245351135c602b39b868d7f82912efc56"},
{file = "openupgradelib-3.11.1.tar.gz", hash = "sha256:b37adbf37b94e649febb99eaa887ee218c3b372061087e35e3901af585d8cbed"},
{file = "openupgradelib-3.12.0-py2.py3-none-any.whl", hash = "sha256:f8f624f4863b2257f760a9959ddd3cfee650b8f4a8740610506c4473ed36b679"},
{file = "openupgradelib-3.12.0.tar.gz", hash = "sha256:3f3cd2475f7eb387fb0c364b7d2828b268dcf6e9c83aecccfbfe5c76cc69e4d7"},
]
[package.dependencies]
@ -4214,6 +4208,21 @@ files = [
[package.dependencies]
pycryptodome = "*"
[[package]]
name = "pexpect"
version = "4.9.0"
description = "Pexpect allows easy control of interactive console applications."
optional = false
python-versions = "*"
groups = ["main"]
files = [
{file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"},
{file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"},
]
[package.dependencies]
ptyprocess = ">=0.5"
[[package]]
name = "phonenumbers"
version = "9.0.17"
@ -4387,6 +4396,30 @@ docs = ["furo (>=2025.9.25)", "proselint (>=0.14)", "sphinx (>=8.2.3)", "sphinx-
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.4.2)", "pytest-cov (>=7)", "pytest-mock (>=3.15.1)"]
type = ["mypy (>=1.18.2)"]
[[package]]
name = "plotly"
version = "6.4.0"
description = "An open-source interactive data visualization library for Python"
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
{file = "plotly-6.4.0-py3-none-any.whl", hash = "sha256:a1062eafbdc657976c2eedd276c90e184ccd6c21282a5e9ee8f20efca9c9a4c5"},
{file = "plotly-6.4.0.tar.gz", hash = "sha256:68c6db2ed2180289ef978f087841148b7efda687552276da15a6e9b92107052a"},
]
[package.dependencies]
narwhals = ">=1.15.1"
packaging = "*"
[package.extras]
dev = ["plotly[dev-optional]"]
dev-build = ["build", "jupyter", "plotly[dev-core]"]
dev-core = ["pytest", "requests", "ruff (==0.11.12)"]
dev-optional = ["anywidget", "colorcet", "fiona (<=1.9.6) ; python_version <= \"3.8\"", "geopandas", "inflect", "numpy", "orjson", "pandas", "pdfrw", "pillow", "plotly-geo", "plotly[dev-build]", "plotly[kaleido]", "polars[timezone]", "pyarrow", "pyshp", "pytz", "scikit-image", "scipy", "shapely", "statsmodels", "vaex ; python_version <= \"3.9\"", "xarray"]
express = ["numpy"]
kaleido = ["kaleido (>=1.1.0)"]
[[package]]
name = "ply"
version = "3.11"
@ -4652,6 +4685,18 @@ files = [
{file = "psycopg2-2.9.9.tar.gz", hash = "sha256:d1454bde93fb1e224166811694d600e746430c006fbb031ea06ecc2ea41bf156"},
]
[[package]]
name = "ptyprocess"
version = "0.7.0"
description = "Run a subprocess in a pseudo terminal"
optional = false
python-versions = "*"
groups = ["main"]
files = [
{file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"},
{file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"},
]
[[package]]
name = "py3dns"
version = "4.0.2"
@ -5181,62 +5226,19 @@ pylint = ">=1.7"
[[package]]
name = "pymssql"
version = "2.3.8"
version = "2.3.9.dev9"
description = "DB-API interface to Microsoft SQL Server for Python. (new Cython-based version)"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "pymssql-2.3.8-cp310-cp310-macosx_13_0_x86_64.whl", hash = "sha256:529c972bfc907baff8f30d9d397471c2786a3293a849490f908c6c79b0687c73"},
{file = "pymssql-2.3.8-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:f463a6e6098fea2a51c099a68f95477e182a218714636f2ccfcb513cef1d43a8"},
{file = "pymssql-2.3.8-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6ac50be6b83f3324b08ea7025d885b4061db0ccd4e71b1ba420a5b5e26d0a4ab"},
{file = "pymssql-2.3.8-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d0f3e2df22e5d73add12613c764bbb5fe7d26119c9cb2aa9de311f514a0060eb"},
{file = "pymssql-2.3.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:bdc738cfae0889940cffd51bb4e45589ddf42c6464ca570dd5982b2b1defc70b"},
{file = "pymssql-2.3.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e3dff5e1523de22a8fa5c304c9c262e56ef28207c6e2551fe2aff8395f03b459"},
{file = "pymssql-2.3.8-cp310-cp310-win32.whl", hash = "sha256:d3bd82ce1b42ae95e0da06b861a31b3c946bdac1ead0226f72a18f4f7eced136"},
{file = "pymssql-2.3.8-cp310-cp310-win_amd64.whl", hash = "sha256:df127a9c5436561734873e5ce06c64abe1c21460e06cbdc02f3310c291bee323"},
{file = "pymssql-2.3.8-cp311-cp311-macosx_13_0_x86_64.whl", hash = "sha256:47cecf5c518b8c20e7e3ac01040976f11520a2ba5726090698a96b3913832a51"},
{file = "pymssql-2.3.8-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:41ea98df3e7f3ee1a9b6e41e612d0cd6c25474583929dcfea6d2cc322ff687b2"},
{file = "pymssql-2.3.8-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a56c4e223c5ddda5e512e18c03fad494f296fc1a2aa03bec38ffd547b7d8c778"},
{file = "pymssql-2.3.8-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:48d18f9e160b30c6d8c9b52172b0abc641504ec5156166c69b8e2caef2a130f8"},
{file = "pymssql-2.3.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4a0848bcc42eab68cbc276f7bcb279eeda4ef1ca214e8aa28836af9f6a9dd100"},
{file = "pymssql-2.3.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:17dd3cdf9f7cd404ccb768d39208b4ac4a80af648c2914ae41d7b4613d9103b5"},
{file = "pymssql-2.3.8-cp311-cp311-win32.whl", hash = "sha256:a88707041e063702b6d643c52b4e86043c4830f714e871c7d2cefb10feb13120"},
{file = "pymssql-2.3.8-cp311-cp311-win_amd64.whl", hash = "sha256:37539c9ee4984ecbdff871b171463f9a18236d697baf04b07b910e610e4b9416"},
{file = "pymssql-2.3.8-cp312-cp312-macosx_13_0_x86_64.whl", hash = "sha256:97d30d1634a6f327cd4803129717640b4c41eb892a73cb009b26c8e25c70350b"},
{file = "pymssql-2.3.8-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:661fea7c04a4f1d4392de36dbf15e8133057ba0afbb0ecc49d5a01d8c6e4f915"},
{file = "pymssql-2.3.8-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:dca810c23dfa3e7becfcd70ae1ffe10971fba4a008df466e27e12e53398caa44"},
{file = "pymssql-2.3.8-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c4ea3e64f46f84da7868f1a47e0fad74002955540907e75afa23fa6c6f561386"},
{file = "pymssql-2.3.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f518f26dccb614ea6bfc6cab49e6b8eb8ff4409b0e669818742a56e172e57549"},
{file = "pymssql-2.3.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dd53fc6f3d92aeadb9a7b7e301c7dce75d681552dc48d6e09da508a129d6a11a"},
{file = "pymssql-2.3.8-cp312-cp312-win32.whl", hash = "sha256:bd311d4371c6ed0165d1dabd9136c89182d484a84b7bd445eb34c549349895a1"},
{file = "pymssql-2.3.8-cp312-cp312-win_amd64.whl", hash = "sha256:8a1c490ba6dc2428d33b4d09274c8b7e4f6efdddb2ac3f1d52be600970e61492"},
{file = "pymssql-2.3.8-cp313-cp313-macosx_13_0_x86_64.whl", hash = "sha256:0076d87b3356e54f0a5dfc3a06a29bc190f6a37ead55f0e715e294cb2855587e"},
{file = "pymssql-2.3.8-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:d74430323c5de9a05d8d6635172329a5ae273ec76216ac4dac14fc8a5cf872d4"},
{file = "pymssql-2.3.8-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:073a9d561bf12936e7893bb8263762c6fbc075d24c323d47c451c18f84be5c58"},
{file = "pymssql-2.3.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:420d777fa02ea22d96f61b71d9105bbf897a97c3149463a7cdd43660713a353d"},
{file = "pymssql-2.3.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6ad9ae915565539b5f31ae78be5e8c95d22bd28933ca062c13921f3be1215f2d"},
{file = "pymssql-2.3.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:135026a2c3f23d56dbc0d3ad0ff4f738e3fd31dc580991cce88e40b544224317"},
{file = "pymssql-2.3.8-cp313-cp313-win32.whl", hash = "sha256:f1bb87e4ce18177b8096dc3a68101cacd4601b1f0a67d98b5a072f7ba9a3b6b1"},
{file = "pymssql-2.3.8-cp313-cp313-win_amd64.whl", hash = "sha256:54ae2ae15b36a8054777c287b22532bcac94f500ddb5a1e0d232abca047cba1e"},
{file = "pymssql-2.3.8-cp314-cp314-macosx_13_0_x86_64.whl", hash = "sha256:7d344e8b4cedab51e9925e08ce6267880f6dac055bd3ad1592d067f9cc2c09bd"},
{file = "pymssql-2.3.8-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:6312649353964b9b71204abd5b89135d105bc2ce04f2a9f465be6bc77ea53d1a"},
{file = "pymssql-2.3.8-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:9f8222024df048a76f2eec0b4f246efaed7a9947a322c251151d683a4bfabe4c"},
{file = "pymssql-2.3.8-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:af6d1d0beed286f73d7d9af0b3a8bdb46cd2a0ad12c92fd601d324ee85c45aa6"},
{file = "pymssql-2.3.8-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9b18e79e1747f5a1b3b28214af235f8e16dff49c512a9be6a13995520dc22af1"},
{file = "pymssql-2.3.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c9d733862687dd1f9406137d43149ee597a1a50263128e7e3543cdecd0ad262d"},
{file = "pymssql-2.3.8-cp314-cp314-win32.whl", hash = "sha256:61b5c1e13803bb15d31b1986cbf0c7fef7f16ddb55ef933d7d78f39adad6f149"},
{file = "pymssql-2.3.8-cp314-cp314-win_amd64.whl", hash = "sha256:d6d303a443ba12d62992c1d2fb0dfec566e2d1462ace9f3382db695f7f0dfbf0"},
{file = "pymssql-2.3.8-cp39-cp39-macosx_13_0_x86_64.whl", hash = "sha256:36cef59bd1fc38ab86ef8b5a4418dc5f58c12915e6ad7019d10365e33ceb05a0"},
{file = "pymssql-2.3.8-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:6672cd9654319a7034401324e8807a987b68a9c7ab90b9b44a7ccfab99be6b19"},
{file = "pymssql-2.3.8-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f618efd281ac92d817b4f1e1cb2dcea75155bfbb9fe2bafaad1a3e9779ff630a"},
{file = "pymssql-2.3.8-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:46f91067d365574b4d10768fe38a54e9af959517f8da2ef823ac22cf9f74c9e7"},
{file = "pymssql-2.3.8-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4ea9a632382684953f3d60b6308506809465efdb49c347b8990486be2c1a5eb1"},
{file = "pymssql-2.3.8-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c416f30a9a54e1face069f1dfe0f8dcdd5c02b3767dfd9ce87dd2ac46a86e1d4"},
{file = "pymssql-2.3.8-cp39-cp39-win32.whl", hash = "sha256:b095f3aa9db0fb104647b066d34827e5cc80d0a957b904ac129993f42d4199bb"},
{file = "pymssql-2.3.8-cp39-cp39-win_amd64.whl", hash = "sha256:85c12f9402e68821a552a09959bdd5c95d136cba41b8f351696c55a47a4b6e94"},
{file = "pymssql-2.3.8.tar.gz", hash = "sha256:dafa4887d697503ac890db316470be22d9b4023487e6425ba67aa0a6681babf5"},
]
files = []
develop = false
[package.source]
type = "git"
url = "https://github.com/pymssql/pymssql.git"
reference = "HEAD"
resolved_reference = "da1ef7e5623ef262dd0e4fbc2119106ca8f7e41e"
[[package]]
name = "pymysql"
@ -5469,20 +5471,20 @@ certifi = "*"
[[package]]
name = "pyrdfa3"
version = "3.6.4"
version = "3.6.2"
description = "pyRdfa distiller/parser library"
optional = false
python-versions = ">=3.8"
python-versions = ">=3.7"
groups = ["main"]
files = [
{file = "pyRdfa3-3.6.4-py3-none-any.whl", hash = "sha256:ed11affa5567ab7afdbc939a58f9286a274447f3ab2999c260c56b5c6e87fb2f"},
{file = "pyrdfa3-3.6.4.tar.gz", hash = "sha256:64712d1a4bf21829652b39715bada6e7c03bcf19cb49f962c190a38f46172243"},
{file = "pyRdfa3-3.6.2-py3-none-any.whl", hash = "sha256:290c2fa966ddd1b45ac94a727da144f5a233ed58c63c370e3d68e6d00b0dee5d"},
{file = "pyRdfa3-3.6.2.tar.gz", hash = "sha256:73681dab957f60901696767388b956a5769c730bc451da6ffb2f0e36f18314c2"},
]
[package.dependencies]
html5lib = ">=1.1"
rdflib = ">=7.0.0"
requests = ">=2.32.3"
rdflib = ">=6.1.1"
requests = ">=2.25.1"
[[package]]
name = "pysaml2"
@ -5653,6 +5655,24 @@ files = [
pyasn1 = ">=0.3.7"
pyasn1_modules = ">=0.1.5"
[[package]]
name = "python-pptx"
version = "1.0.2"
description = "Create, read, and update PowerPoint 2007+ (.pptx) files."
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
{file = "python_pptx-1.0.2-py3-none-any.whl", hash = "sha256:160838e0b8565a8b1f67947675886e9fea18aa5e795db7ae531606d68e785cba"},
{file = "python_pptx-1.0.2.tar.gz", hash = "sha256:479a8af0eaf0f0d76b6f00b0887732874ad2e3188230315290cd1f9dd9cc7095"},
]
[package.dependencies]
lxml = ">=3.1.0"
Pillow = ">=3.3.2"
typing-extensions = ">=4.9.0"
XlsxWriter = ">=0.5.7"
[[package]]
name = "python-resize-image"
version = "1.1.20"
@ -6551,6 +6571,28 @@ webencodings = ">=0.4"
doc = ["sphinx", "sphinx_rtd_theme"]
test = ["pytest", "ruff"]
[[package]]
name = "tldextract"
version = "5.3.0"
description = "Accurately separates a URL's subdomain, domain, and public suffix, using the Public Suffix List (PSL). By default, this includes the public ICANN TLDs and their exceptions. You can optionally support the Public Suffix List's private domains as well."
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "tldextract-5.3.0-py3-none-any.whl", hash = "sha256:f70f31d10b55c83993f55e91ecb7c5d84532a8972f22ec578ecfbe5ea2292db2"},
{file = "tldextract-5.3.0.tar.gz", hash = "sha256:b3d2b70a1594a0ecfa6967d57251527d58e00bb5a91a74387baa0d87a0678609"},
]
[package.dependencies]
filelock = ">=3.0.8"
idna = "*"
requests = ">=2.1.0"
requests-file = ">=1.4"
[package.extras]
release = ["build", "twine"]
testing = ["mypy", "pytest", "pytest-gitignore", "pytest-mock", "responses", "ruff", "syrupy", "tox", "tox-uv", "types-filelock", "types-requests"]
[[package]]
name = "tomlkit"
version = "0.13.3"
@ -6734,6 +6776,70 @@ secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.
socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
zstd = ["zstandard (>=0.18.0)"]
[[package]]
name = "uvloop"
version = "0.22.1"
description = "Fast implementation of asyncio event loop on top of libuv"
optional = false
python-versions = ">=3.8.1"
groups = ["main"]
files = [
{file = "uvloop-0.22.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ef6f0d4cc8a9fa1f6a910230cd53545d9a14479311e87e3cb225495952eb672c"},
{file = "uvloop-0.22.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7cd375a12b71d33d46af85a3343b35d98e8116134ba404bd657b3b1d15988792"},
{file = "uvloop-0.22.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ac33ed96229b7790eb729702751c0e93ac5bc3bcf52ae9eccbff30da09194b86"},
{file = "uvloop-0.22.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:481c990a7abe2c6f4fc3d98781cc9426ebd7f03a9aaa7eb03d3bfc68ac2a46bd"},
{file = "uvloop-0.22.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a592b043a47ad17911add5fbd087c76716d7c9ccc1d64ec9249ceafd735f03c2"},
{file = "uvloop-0.22.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1489cf791aa7b6e8c8be1c5a080bae3a672791fcb4e9e12249b05862a2ca9cec"},
{file = "uvloop-0.22.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c60ebcd36f7b240b30788554b6f0782454826a0ed765d8430652621b5de674b9"},
{file = "uvloop-0.22.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3b7f102bf3cb1995cfeaee9321105e8f5da76fdb104cdad8986f85461a1b7b77"},
{file = "uvloop-0.22.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:53c85520781d84a4b8b230e24a5af5b0778efdb39142b424990ff1ef7c48ba21"},
{file = "uvloop-0.22.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:56a2d1fae65fd82197cb8c53c367310b3eabe1bbb9fb5a04d28e3e3520e4f702"},
{file = "uvloop-0.22.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:40631b049d5972c6755b06d0bfe8233b1bd9a8a6392d9d1c45c10b6f9e9b2733"},
{file = "uvloop-0.22.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:535cc37b3a04f6cd2c1ef65fa1d370c9a35b6695df735fcff5427323f2cd5473"},
{file = "uvloop-0.22.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:fe94b4564e865d968414598eea1a6de60adba0c040ba4ed05ac1300de402cd42"},
{file = "uvloop-0.22.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:51eb9bd88391483410daad430813d982010f9c9c89512321f5b60e2cddbdddd6"},
{file = "uvloop-0.22.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:700e674a166ca5778255e0e1dc4e9d79ab2acc57b9171b79e65feba7184b3370"},
{file = "uvloop-0.22.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7b5b1ac819a3f946d3b2ee07f09149578ae76066d70b44df3fa990add49a82e4"},
{file = "uvloop-0.22.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e047cc068570bac9866237739607d1313b9253c3051ad84738cbb095be0537b2"},
{file = "uvloop-0.22.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:512fec6815e2dd45161054592441ef76c830eddaad55c8aa30952e6fe1ed07c0"},
{file = "uvloop-0.22.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:561577354eb94200d75aca23fbde86ee11be36b00e52a4eaf8f50fb0c86b7705"},
{file = "uvloop-0.22.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cdf5192ab3e674ca26da2eada35b288d2fa49fdd0f357a19f0e7c4e7d5077c8"},
{file = "uvloop-0.22.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e2ea3d6190a2968f4a14a23019d3b16870dd2190cd69c8180f7c632d21de68d"},
{file = "uvloop-0.22.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0530a5fbad9c9e4ee3f2b33b148c6a64d47bbad8000ea63704fa8260f4cf728e"},
{file = "uvloop-0.22.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bc5ef13bbc10b5335792360623cc378d52d7e62c2de64660616478c32cd0598e"},
{file = "uvloop-0.22.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1f38ec5e3f18c8a10ded09742f7fb8de0108796eb673f30ce7762ce1b8550cad"},
{file = "uvloop-0.22.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3879b88423ec7e97cd4eba2a443aa26ed4e59b45e6b76aabf13fe2f27023a142"},
{file = "uvloop-0.22.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:4baa86acedf1d62115c1dc6ad1e17134476688f08c6efd8a2ab076e815665c74"},
{file = "uvloop-0.22.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:297c27d8003520596236bdb2335e6b3f649480bd09e00d1e3a99144b691d2a35"},
{file = "uvloop-0.22.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c1955d5a1dd43198244d47664a5858082a3239766a839b2102a269aaff7a4e25"},
{file = "uvloop-0.22.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b31dc2fccbd42adc73bc4e7cdbae4fc5086cf378979e53ca5d0301838c5682c6"},
{file = "uvloop-0.22.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:93f617675b2d03af4e72a5333ef89450dfaa5321303ede6e67ba9c9d26878079"},
{file = "uvloop-0.22.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:37554f70528f60cad66945b885eb01f1bb514f132d92b6eeed1c90fd54ed6289"},
{file = "uvloop-0.22.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:b76324e2dc033a0b2f435f33eb88ff9913c156ef78e153fb210e03c13da746b3"},
{file = "uvloop-0.22.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:badb4d8e58ee08dad957002027830d5c3b06aea446a6a3744483c2b3b745345c"},
{file = "uvloop-0.22.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b91328c72635f6f9e0282e4a57da7470c7350ab1c9f48546c0f2866205349d21"},
{file = "uvloop-0.22.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:daf620c2995d193449393d6c62131b3fbd40a63bf7b307a1527856ace637fe88"},
{file = "uvloop-0.22.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6cde23eeda1a25c75b2e07d39970f3374105d5eafbaab2a4482be82f272d5a5e"},
{file = "uvloop-0.22.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:80eee091fe128e425177fbd82f8635769e2f32ec9daf6468286ec57ec0313efa"},
{file = "uvloop-0.22.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:017bd46f9e7b78e81606329d07141d3da446f8798c6baeec124260e22c262772"},
{file = "uvloop-0.22.1-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c3e5c6727a57cb6558592a95019e504f605d1c54eb86463ee9f7a2dbd411c820"},
{file = "uvloop-0.22.1-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:57df59d8b48feb0e613d9b1f5e57b7532e97cbaf0d61f7aa9aa32221e84bc4b6"},
{file = "uvloop-0.22.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:55502bc2c653ed2e9692e8c55cb95b397d33f9f2911e929dc97c4d6b26d04242"},
{file = "uvloop-0.22.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:4a968a72422a097b09042d5fa2c5c590251ad484acf910a651b4b620acd7f193"},
{file = "uvloop-0.22.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b45649628d816c030dba3c80f8e2689bab1c89518ed10d426036cdc47874dfc4"},
{file = "uvloop-0.22.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ea721dd3203b809039fcc2983f14608dae82b212288b346e0bfe46ec2fab0b7c"},
{file = "uvloop-0.22.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ae676de143db2b2f60a9696d7eca5bb9d0dd6cc3ac3dad59a8ae7e95f9e1b54"},
{file = "uvloop-0.22.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:17d4e97258b0172dfa107b89aa1eeba3016f4b1974ce85ca3ef6a66b35cbf659"},
{file = "uvloop-0.22.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:05e4b5f86e621cf3927631789999e697e58f0d2d32675b67d9ca9eb0bca55743"},
{file = "uvloop-0.22.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:286322a90bea1f9422a470d5d2ad82d38080be0a29c4dd9b3e6384320a4d11e7"},
{file = "uvloop-0.22.1.tar.gz", hash = "sha256:6c84bae345b9147082b17371e3dd5d42775bddce91f885499017f4607fdaf39f"},
]
[package.extras]
dev = ["Cython (>=3.0,<4.0)", "setuptools (>=60)"]
docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx_rtd_theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"]
test = ["aiohttp (>=3.10.5)", "flake8 (>=6.1,<7.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=25.3.0,<25.4.0)", "pycodestyle (>=2.11.0,<2.12.0)"]
[[package]]
name = "validate-email"
version = "1.3"
@ -7351,4 +7457,4 @@ bindings = ["ghostscript"]
[metadata]
lock-version = "2.1"
python-versions = ">=3.12.10,<3.13"
content-hash = "0e97844a7cf0de05cca9a8c0a75bd07adea905a048463f4a11440b44085c0094"
content-hash = "ba7450664480f89108a65126adf1fb86de79d27e7597433ee1ccc72f50fb2f1c"

View file

@ -20,23 +20,23 @@ authors = [ "Mathieu Benoit <mathben@technolibre.ca>",]
[tool.poetry.dependencies]
python = ">=3.12.10,<3.13"
asn1crypto = "1.5.1"
astor = "^0.8.1"
avalara = "^25.9.0"
babel = "2.10.3"
bandit = "^1.8.6"
base64io = "^1.0.3"
beautifulsoup4 = "4.13.5"
bokeh = "3.6.3"
boto3 = "^1.40.64"
boto3 = "^1.40.67"
cachetools = "^6.2.1"
cairosvg = "^2.8.2"
caldav = "1.3.9"
cbor2 = "5.6.2"
chardet = "5.2.0"
code-writer = "^1.2.0"
colorama = "^0.4.6"
cryptography = "46.0.3"
cssselect = "^1.3.0"
cython = "^3.1.6"
cython = "^3.2.0"
decorator = "5.1.1"
docutils = "0.20.1"
dropbox = "^12.0.2"
@ -59,7 +59,7 @@ greenlet = "3.0.3"
httpagentparser = "^1.9.5"
icalendar = "5.0.13"
idna = "3.6"
img2pdf = "^0.6.1"
img2pdf = "^0.6.3"
isort = "6.1.0"
jinja2 = "3.1.2"
js2py = "^0.74"
@ -81,9 +81,9 @@ num2words = "0.5.13"
numpy-stl = "^3.2.0"
odoorpc = "^0.10.1"
ofxparse = "0.21"
openai = "^2.6.1"
openai = "^2.7.1"
openpyxl = "3.1.2"
openupgradelib = "^3.11.1"
openupgradelib = "^3.12.0"
openwebui-client = ">=0.3.0"
pandas = ">=0.25.3"
paramiko = "<4.0.0"
@ -91,8 +91,10 @@ passlib = "1.7.4"
pathspec = "^0.12.1"
pdf2image = "^1.17.0"
pdfminer = "^20191125"
pexpect = "^4.9.0"
phonenumbers = "^9.0.17"
pillow = "10.2.0"
plotly = "^6.4.0"
polib = "1.1.1"
pre-commit = "^4.3.0"
premailer = "^3.10.0"
@ -110,7 +112,6 @@ pyjsparser = "^2.7.1"
pyjwt = "^2.10.1"
pylint = "3.3.9"
pylint-odoo = "^9.3.22"
pymssql = "^2.3.8"
pymysql = "^1.1.2"
pyncclient = "^0.7"
pyopenssl = "25.3.0"
@ -125,6 +126,7 @@ python-dotenv = ">=1.0.0"
python-jose = "^3.5.0"
python-json-logger = "^4.0.0"
python-ldap = "3.4.4"
python-pptx = "^1.0.2"
python-resize-image = "^1.1.20"
python-slugify = "^8.0.4"
python-stdnum = "1.19"
@ -148,10 +150,12 @@ sentry-sdk = ">=2.0.0,<=2.22.0"
setuptools = "80.9.0"
shapely = "^2.1.2"
statsd = "^4.0.1"
tldextract = "^5.3.0"
tweepy = "^4.16.0"
twilio = "^9.8.5"
unidecode = "^1.4.0"
urllib3 = "2.0.7"
uvloop = "^0.22.1"
validate-email = "^1.3"
vobject = "0.9.6.1"
w3lib = "^2.3.1"
@ -163,6 +167,9 @@ xlwt = "1.3.0"
xmltodict = "0.13.0"
zeep = "4.2.1"
[tool.poetry.dependencies.astor]
git = "https://github.com/berkerpeksag/astor.git"
[tool.poetry.dependencies.black]
git = "https://github.com/psf/black.git"
rev = "24.8.0"
@ -171,6 +178,9 @@ rev = "24.8.0"
extras = [ "s3",]
version = "^2025.10.0"
[tool.poetry.dependencies.pymssql]
git = "https://github.com/pymssql/pymssql.git"
[tool.poetry.dependencies.pysaml2]
git = "https://github.com/prauscher/pysaml2.git"
rev = "replace-pyopenssl"

View file

@ -64,3 +64,9 @@ cryptography==46.0.3
pyopenssl==25.3.0
# This will ignore pyopenssl from pysaml2==7.5.4
git+https://github.com/prauscher/pysaml2.git@replace-pyopenssl
# Fix compilation, until pymssql==2.3.9 is release
git+https://github.com/pymssql/pymssql.git
# Force last version, because too old into pip
git+https://github.com/berkerpeksag/astor.git

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse
@ -14,7 +14,6 @@ import uuid
from git import Repo
from git.exc import InvalidGitRepositoryError, NoSuchPathError
logging.basicConfig(
format=(
"%(asctime)s,%(msecs)d %(levelname)-8s [%(filename)s:%(lineno)d]"
@ -383,10 +382,7 @@ class ProjectManagement:
os.system(cmd)
if not self.keep_bd_alive:
cmd = (
"./odoo_bin.sh db --drop --database"
f" {bd_name_demo}"
)
cmd = "./odoo_bin.sh db --drop --database" f" {bd_name_demo}"
_logger.info(cmd)
os.system(cmd)
@ -467,10 +463,7 @@ class ProjectManagement:
os.system(cmd)
if not self.keep_bd_alive:
cmd = (
"./odoo_bin.sh db --drop --database"
f" {bd_name_template}"
)
cmd = "./odoo_bin.sh db --drop --database" f" {bd_name_template}"
_logger.info(cmd)
os.system(cmd)
@ -538,10 +531,7 @@ class ProjectManagement:
os.system(cmd)
if not self.keep_bd_alive:
cmd = (
"./odoo_bin.sh db --drop --database"
f" {bd_name_generator}"
)
cmd = "./odoo_bin.sh db --drop --database" f" {bd_name_generator}"
_logger.info(cmd)
os.system(cmd)

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,40 +1,48 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
print("This script only work with localhost:8069, not working with remote instance.")
print(
"This script only work with localhost:8069, not working with remote instance."
)
import requests
import sys
import logging
import sys
from pathlib import Path
ODOO_URL = '' # Your Odoo server URL
DATABASE_NAME = ''
MASTER_PASSWORD = ''
import requests
ODOO_URL = "" # Your Odoo server URL
DATABASE_NAME = ""
MASTER_PASSWORD = ""
# BACKUP_FORMAT = env('BACKUP_FORMAT', default='zip') # 'zip' or 'dump'
BACKUP_FORMAT = 'zip' # 'zip' or 'dump'
OUTPUT_FILE_NAME = f'{DATABASE_NAME}_backup.{BACKUP_FORMAT}'
BACKUP_FORMAT = "zip" # 'zip' or 'dump'
OUTPUT_FILE_NAME = f"{DATABASE_NAME}_backup.{BACKUP_FORMAT}"
# --- Logger Setup ---
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# TODO not working with remote, only localhost
logger.error("This script is not working with remote instance, only http://127.0.0.1:8069")
logger.error(
"This script is not working with remote instance, only http://127.0.0.1:8069"
)
# --- Function to download the database ---
def download_odoo_db():
logger.info(f"Attempting to download database '{DATABASE_NAME}' from URL '{ODOO_URL}'...")
logger.info(
f"Attempting to download database '{DATABASE_NAME}' from URL '{ODOO_URL}'..."
)
# URL for the backup endpoint
backup_url = f'{ODOO_URL}/web/database/backup'
backup_url = f"{ODOO_URL}/web/database/backup"
# Form data for the POST request
payload = {
'master_pwd': MASTER_PASSWORD,
'name': DATABASE_NAME,
'backup_format': BACKUP_FORMAT,
"master_pwd": MASTER_PASSWORD,
"name": DATABASE_NAME,
"backup_format": BACKUP_FORMAT,
}
try:
@ -43,20 +51,28 @@ def download_odoo_db():
response.raise_for_status() # Raise an exception for bad status codes
# --- VALIDATION ---
content_type = response.headers.get('Content-Type', '').split(';')[0]
content_type = response.headers.get("Content-Type", "").split(";")[0]
# Check if the content type is valid
expected_types = ['application/zip', 'application/octet-stream']
expected_types = ["application/zip", "application/octet-stream"]
if content_type not in expected_types:
logger.error(f"ERROR: Expected one of {expected_types} but got {content_type}.")
logger.error("This usually indicates a server-side error or an incorrect master password.")
logger.error(
f"ERROR: Expected one of {expected_types} but got {content_type}."
)
logger.error(
"This usually indicates a server-side error or an incorrect master password."
)
sys.exit(1)
# Check if the content is an HTML page (to handle incorrect passwords)
first_chunk = next(response.iter_content(chunk_size=128), b'')
if first_chunk.startswith(b'<'):
logger.error("ERROR: It seems the server returned an HTML page instead of a database file.")
logger.error("This is often due to an incorrect master password or an invalid request.")
first_chunk = next(response.iter_content(chunk_size=128), b"")
if first_chunk.startswith(b"<"):
logger.error(
"ERROR: It seems the server returned an HTML page instead of a database file."
)
logger.error(
"This is often due to an incorrect master password or an invalid request."
)
logger.error("Server Response (First 200 chars):")
logger.error(response.text[:200])
sys.exit(1)
@ -65,26 +81,35 @@ def download_odoo_db():
logger.info(f"Download started, saving to '{OUTPUT_FILE_NAME}'...")
output_path = Path(OUTPUT_FILE_NAME)
with open(output_path, 'wb') as f:
with open(output_path, "wb") as f:
# Write the content from the first chunk to the file
f.write(first_chunk)
# Continue writing the rest of the stream in chunks
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
logger.info(f"Download successful! File saved at: {output_path.resolve()}")
logger.info(
f"Download successful! File saved at: {output_path.resolve()}"
)
except requests.exceptions.RequestException as e:
logger.error(f"An error occurred while connecting to the Odoo server: {e}")
logger.error(
f"An error occurred while connecting to the Odoo server: {e}"
)
except Exception as e:
logger.error(f"An unexpected error occurred: {e}")
# --- Script execution ---
if __name__ == '__main__':
if __name__ == "__main__":
# Add a simple check to ensure the user has configured the variables
if ODOO_URL == 'http://localhost:8069' and DATABASE_NAME == 'your_database_name':
logger.error("Please configure the ODOO_URL, DATABASE_NAME, and MASTER_PASSWORD variables at the start of the script.")
if (
ODOO_URL == "http://localhost:8069"
and DATABASE_NAME == "your_database_name"
):
logger.error(
"Please configure the ODOO_URL, DATABASE_NAME, and MASTER_PASSWORD variables at the start of the script."
)
sys.exit(1)
download_odoo_db()

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
from collections import defaultdict
@ -161,19 +161,19 @@ def delete_record(cr):
cr.execute(query_search)
query_search = """
DELETE FROM `tbl_commande_membre_produit`
DELETE FROM `tbl_commande_membre_produit`
WHERE NoFournisseurProduitCommande in (22659, 22724, 22662, 22663, 22732, 22670, 22705, 22737, 22741, 22679, 22680, 22682, 22655);
"""
cr.execute(query_search)
query_search = """
DELETE FROM `tbl_echange_service`
DELETE FROM `tbl_echange_service`
WHERE NoMembreVendeur in (7703);
"""
cr.execute(query_search)
query_search = """
DELETE FROM `tbl_categorie_sous_categorie`
DELETE FROM `tbl_categorie_sous_categorie`
WHERE NoCategorie in (999);
"""
cr.execute(query_search)
@ -210,7 +210,7 @@ def migrate_record(cr):
i = 0
for sous_categorie_id in lst_sous_categorie:
i += 1
query_search = f"""UPDATE tbl_sous_categorie set NoSousCategorieId={i}
query_search = f"""UPDATE tbl_sous_categorie set NoSousCategorieId={i}
WHERE NoCategorie={sous_categorie_id[1]} and NoSousCategorie='{sous_categorie_id[0]}'
"""
cr.execute(query_search)
@ -232,7 +232,7 @@ def migrate_record(cr):
f"Get null from {categorie_sous_categorie_id[2]} and"
f" {categorie_sous_categorie_id[1]}"
)
query_search = f"""UPDATE tbl_categorie_sous_categorie set NoSousCategorieId={id_sous_categorie}
query_search = f"""UPDATE tbl_categorie_sous_categorie set NoSousCategorieId={id_sous_categorie}
WHERE NoCategorieSousCategorie={categorie_sous_categorie_id[0]}
"""
cr.execute(query_search)

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse
@ -301,18 +301,13 @@ def main():
all_temp_bd = []
# Step 0, drop and restore
cmd_drop_db = (
f"./odoo_bin.sh db --drop --database {bd_temp_name}"
)
cmd_drop_db = f"./odoo_bin.sh db --drop --database {bd_temp_name}"
all_temp_bd.append(bd_temp_name)
run_cmd(cmd_drop_db)
if not base_image_name or base_image_name == image_name_to_generate:
with_demo = dct_config_image.get("with_demo")
# Create a new one
cmd = (
f"./odoo_bin.sh db --create --database"
f" {bd_temp_name}"
)
cmd = f"./odoo_bin.sh db --create --database" f" {bd_temp_name}"
if with_demo:
cmd += " --demo"
else:
@ -352,9 +347,7 @@ def main():
# Step 6, clean if ask
if not config.keep_database:
for db_name in all_temp_bd:
cmd_drop_db = (
f"./odoo_bin.sh db --drop --database {db_name}"
)
cmd_drop_db = f"./odoo_bin.sh db --drop --database {db_name}"
run_cmd(cmd_drop_db)

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import requests

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse
@ -7,7 +7,6 @@ import logging
import os
import sys
new_path = os.path.normpath(
os.path.join(os.path.dirname(__file__), "..", "..")
)

View file

@ -31,7 +31,6 @@ if [[ ${EL_MINIMAL_ADDONS} = "False" ]]; then
printf "${EL_HOME_ODOO_PROJECT}/addons/CybroOdoo_OpenHRMS," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/ERPLibre_erplibre_addons," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/MathBenTech_development," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/MathBenTech_odoo-business-spending-management-quebec-canada," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_account-analytic," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_account-budgeting," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_account-closing," >> "${EL_CONFIG_FILE}"
@ -43,10 +42,9 @@ if [[ ${EL_MINIMAL_ADDONS} = "False" ]]; then
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_account-invoicing," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_account-payment," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_account-reconcile," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_agreement," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_apps-store," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_automation," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_bank-payment," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_bank-payment-alternative," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_bank-statement-import," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_brand," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_business-requirement," >> "${EL_CONFIG_FILE}"
@ -59,9 +57,9 @@ if [[ ${EL_MINIMAL_ADDONS} = "False" ]]; then
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_connector-jira," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_connector-telephony," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_contract," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_cooperative," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_credit-control," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_crm," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_crowdfunding," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_currency," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_data-protection," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_ddmrp," >> "${EL_CONFIG_FILE}"
@ -70,31 +68,25 @@ if [[ ${EL_MINIMAL_ADDONS} = "False" ]]; then
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_donation," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_e-commerce," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_edi," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_edi-framework," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_event," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_field-service," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_fleet," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_geospatial," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_helpdesk," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_hr," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_hr-expense," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_hr-holidays," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_interface-github," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_intrastat-extrastat," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_iot," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_knowledge," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_l10n-canada," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_mail," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_maintenance," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_management-system," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_manufacture," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_margin-analysis," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_mis-builder," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_mis-builder-contrib," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_multi-company," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_odoo-pim," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_operating-unit," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_partner-contact," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_pms," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_pos," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_product-attribute," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_product-configurator," >> "${EL_CONFIG_FILE}"
@ -103,65 +95,44 @@ if [[ ${EL_MINIMAL_ADDONS} = "False" ]]; then
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_project," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_project-agile," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_project-reporting," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_purchase-reporting," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_purchase-workflow," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_queue," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_repair," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_report-print-send," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_reporting-engine," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_rest-framework," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_rma," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_sale-blanket," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_sale-channel," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_sale-prebook," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_sale-promotion," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_sale-reporting," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_sale-workflow," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_search-engine," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_server-auth," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_server-backend," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_server-brand," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_server-env," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_server-tools," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_server-ux," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_shift-planning," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_sign," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_social," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_spreadsheet," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_stock-logistics-availability," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_stock-logistics-barcode," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_stock-logistics-orderpoint," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_stock-logistics-reporting," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_stock-logistics-request," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_stock-logistics-tracking," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_stock-logistics-transport," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_stock-logistics-putaway," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_stock-logistics-warehouse," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_stock-logistics-workflow," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_stock-weighing," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_storage," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_survey," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_timesheet," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_vertical-abbey," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_vertical-association," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_vertical-hotel," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_vertical-isp," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_vertical-rental," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_vertical-travel," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_web," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_web-api," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_website," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_website-cms," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_wms," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OmniaGit_odooplm," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/TechnoLibre_odoo-code-generator," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/TechnoLibre_odoo-code-generator-template," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/bemade_bemade-addons," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/camptocamp_odoo-cloud-platform," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/cetmix_cetmix-tower," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/dhongu_deltatech," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/it-projects-llc_saas-addons," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/muk-it_muk_web," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/muk-it_odoo-modules," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/novacode-nl_odoo-formio," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/odoomates_odooapps," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/openeducat_openeducat_erp," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/tegin_medical-fhir," >> "${EL_CONFIG_FILE}"
fi
printf "\n" >> "${EL_CONFIG_FILE}"

View file

@ -1,6 +1,5 @@
#!/usr/bin/env bash
rm -fr ./.repo
rm -rf ./odoo ./addons*/* ./script/OCA* ./image_db ./doc/itpp* ./doc/odoo_*
rm -rf addons*
#mkdir -p addons/addons
# TODO create a script to find all repo to delete it
#rm -fr ./.repo
rm -rf ./odoo1* ./script/OCA* ./image_db ./doc/itpp* ./doc/odoo_*

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse
@ -24,7 +24,9 @@ DEFAULT_PATH_MANIFEST_ODOO_CONF = os.path.join("conf", "git_manifest_odoo.csv")
DEFAULT_PATH_MANIFEST_PRIVATE_CONF = os.path.join(
"private", "default_git_manifest.csv"
)
DEFAULT_PATH_INSTALLED_ODOO_VERSION = os.path.join(".repo", "installed_odoo_version.txt")
DEFAULT_PATH_INSTALLED_ODOO_VERSION = os.path.join(
".repo", "installed_odoo_version.txt"
)
def get_config():
@ -44,7 +46,11 @@ def get_config():
"--input",
help="First manifest to merge into input2. Second manifest, overwrite by input1.",
)
parser.add_argument("--output", default=".repo/local_manifests/erplibre_manifest.xml", help="Output of new manifest")
parser.add_argument(
"--output",
default=".repo/local_manifests/erplibre_manifest.xml",
help="Output of new manifest",
)
parser.add_argument(
"--att_revision_only",
action="store_true",
@ -89,11 +95,14 @@ def main():
if os.path.exists(DEFAULT_PATH_INSTALLED_ODOO_VERSION):
with open(DEFAULT_PATH_INSTALLED_ODOO_VERSION, "r") as f:
lst_installed_odoo_version = [a.strip() for a in f.readlines()]
lst_installed_odoo_version = [
a.strip() for a in f.readlines()
]
if lst_installed_odoo_version:
for installed_odoo_version in lst_installed_odoo_version:
path_manifest_odoo_version = os.path.join(
"manifest", f"git_manifest_{installed_odoo_version}.xml"
"manifest",
f"git_manifest_{installed_odoo_version}.xml",
)
if os.path.exists(path_manifest_odoo_version):
lst_input.append(path_manifest_odoo_version)
@ -102,7 +111,8 @@ def main():
f"ERROR: {path_manifest_odoo_version} does not exist"
)
path_manifest_odoo_version = os.path.join(
"manifest", f"git_manifest_{installed_odoo_version}_dev.xml"
"manifest",
f"git_manifest_{installed_odoo_version}_dev.xml",
)
if os.path.exists(path_manifest_odoo_version):
lst_input.append(path_manifest_odoo_version)

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import os

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse
@ -26,6 +26,7 @@ _logger = logging.getLogger(__name__)
PROJECT_NAME = os.path.basename(os.getcwd())
IDEA_PATH = "./.idea"
DEFAULT_ODOO_BIN = "./odoo/odoo-bin" # Will be replaced dynamic
IDEA_MISC = os.path.join(IDEA_PATH, "misc.xml")
IDEA_WORKSPACE = os.path.join(IDEA_PATH, "workspace.xml")
VCS_WORKSPACE = os.path.join(IDEA_PATH, "vcs.xml")
@ -35,6 +36,12 @@ PATH_DEFAULT_CONFIGURATION = "./conf/pycharm_default_configuration.csv"
PATH_DEFAULT_CONFIGURATION_PRIVATE = (
"./private/pycharm_default_configuration.private.csv"
)
if os.path.isfile(".odoo-version"):
with open(".odoo-version") as txt:
odoo_version = txt.read()
DEFAULT_ODOO_BIN_UPDATE = f"./odoo{odoo_version}/odoo/odoo-bin"
else:
DEFAULT_ODOO_BIN_UPDATE = None
def get_config():
@ -342,6 +349,10 @@ def add_configuration(dct_xml, file_name, config):
conf_default = bool(default_conf.get("default"))
if conf_default:
last_default = f"Python.{conf_name}"
if DEFAULT_ODOO_BIN_UPDATE:
conf_script_path = conf_script_path.replace(
DEFAULT_ODOO_BIN, DEFAULT_ODOO_BIN_UPDATE
)
conf_script_path_replace = (
conf_script_path
if not conf_script_path.startswith("./")

View file

@ -1,15 +1,15 @@
#!/usr/bin/env bash
install_package() {
local package_name=$1
local package_name=$1
# Check package is already installed
if pacman -Qs "$package_name" > /dev/null; then
echo "$package_name is already installed."
else
echo "Installation of package $package_name..."
yes|yay -S "$package_name"
fi
# Check package is already installed
if pacman -Qs "$package_name" >/dev/null; then
echo "$package_name is already installed."
else
echo "Installation of package $package_name..."
yes | yay -S "$package_name"
fi
}
# Odoo installation
@ -18,6 +18,7 @@ install_package postgresql
install_package mariadb
install_package libev
install_package wkhtmltopdf
install_package freetds
echo "Need password to create symbolic link, create postgres user and install npm :"
sudo ln -fs /usr/lib/libldap.so /usr/lib/libldap_r.so

View file

@ -82,7 +82,7 @@ if [[ $retVal -ne 0 ]]; then
echo "apt-get debian tool installation error."
exit 1
fi
sudo apt-get install libmariadbd-dev -y
sudo apt-get install libmariadbd-dev freetds-dev -y
retVal=$?
if [[ $retVal -ne 0 ]]; then
echo "apt-get libmariadb installation error."

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import asyncio

View file

@ -2,6 +2,7 @@
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import os
import subprocess
IGNORE_EXTENSION = []
@ -15,51 +16,89 @@ def execute_shell(cmd):
def get_modified_files():
lst_cmd_git_status = ["git", "status", "--porcelain"]
print(" ".join(lst_cmd_git_status))
lst_cmd_git_status_repo = [
".venv.erplibre/bin/repo",
"forall",
"-p",
"-c",
"git status -s",
]
try:
print(" ".join(lst_cmd_git_status))
result = subprocess.run(
lst_cmd_git_status,
capture_output=True,
text=True,
check=True,
)
lines = result.stdout.strip().split("\n")
lines_local = result.stdout.strip().split("\n")
lst_lines = [(".", lines_local)]
print(" ".join(lst_cmd_git_status_repo))
result = subprocess.run(
lst_cmd_git_status_repo,
capture_output=True,
text=True,
check=True,
)
lines_project = result.stdout.strip().split("\n\n")
for str_project_line in lines_project:
line_repo = str_project_line.split("\n")
projet_name = line_repo[0]
lines_local = line_repo[1:]
directory_project = projet_name[len("project ") :]
lst_lines.append((directory_project, lines_local))
modified_files = []
for line in lines:
if not line:
continue
for directory, lines in lst_lines:
for line in lines:
if not line:
continue
try:
if "->" in line:
# Example : M file_01 -> file_02
status, old_file_path, code, file_path = (
line.strip().replace(" ", " ").split(" ")
)
try:
has_space = False
file_path_space = ""
if '"' in line:
has_space = True
file_path_space = line[
line.index('"') + 1 : line.rindex('"')
]
line = line.replace(f'"{file_path_space}"', "replace")
if "->" in line:
# Example : M file_01 -> file_02
status, old_file_path, code, file_path = (
line.strip().replace(" ", " ").split(" ")
)
else:
# Example : M file_01
status, file_path = (
line.strip().replace(" ", " ").split(" ")
)
if has_space:
file_path = file_path_space
file_path = os.path.join(directory, file_path)
except Exception as e:
print(f"'{line}'")
raise e
if (
status == "M"
or status == "A"
or status == "AM"
or status == "MM"
or status == "R"
or status == "RM"
or status == "??"
):
modified_files.append((status, file_path))
elif status == "D":
# Ignore to format removed file
pass
else:
# Example : M file_01
status, file_path = (
line.strip().replace(" ", " ").split(" ")
)
except Exception as e:
print(f"'{line}'")
raise e
if (
status == "M"
or status == "A"
or status == "AM"
or status == "MM"
or status == "R"
or status == "RM"
or status == "??"
):
modified_files.append((status, file_path))
elif status == "D":
# Ignore to format removed file
pass
else:
print(f"Not supported status '{status}'")
print(f"Not supported status '{status}'")
return modified_files
except subprocess.CalledProcessError as e:

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import json

View file

@ -0,0 +1,199 @@
#!/usr/bin/env python3
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse
import os
import sys
import time
from selenium.webdriver.common.by import By
new_path = os.path.normpath(
os.path.join(os.path.dirname(__file__), "..", "..", "..")
)
sys.path.append(new_path)
from script.selenium import selenium_lib, web_login
def run(config, selenium_tool):
selenium_tool.inject_cursor()
if config.open_me_devops:
selenium_tool.odoo_website_menu_click("Erplibre DevOps")
if config.generate_code:
selenium_tool.click_with_mouse_move(
by=By.CSS_SELECTOR, value="button.oe_stat_button:nth-child(1)"
)
selenium_tool.click_with_mouse_move(
by=By.NAME, value="state_goto_code_module"
)
selenium_tool.input_text_with_mouse_move(
by=By.ID,
value="working_module_name_1",
text_value="test_coucou",
)
selenium_tool.click_with_mouse_move(
by=By.NAME, value="action_code_module_autocomplete_module_path"
)
time.sleep(1)
selenium_tool.click_with_mouse_move(
by=By.XPATH, value="//a[contains(text(), 'Ajouter une ligne')]"
)
selenium_tool.click_with_mouse_move(
by=By.CLASS_NAME, value="o_create_button"
)
selenium_tool.input_text_with_mouse_move(
by=By.XPATH,
value="//div[@name='name']/input",
text_value="x_coucou",
)
selenium_tool.click_with_mouse_move(
by=By.XPATH,
value="//h4[contains(text(), 'Créer Model')]/../../main//a[contains(text(), 'Ajouter une ligne')]",
)
selenium_tool.input_text_with_mouse_move(
by=By.XPATH,
value="//h4[contains(text(), 'Créer Field')]/../../main//div[@name='name']/input",
text_value="x_name",
)
selenium_tool.click_with_mouse_move(
by=By.XPATH,
value="//h4[contains(text(), 'Créer Field')]/../../footer/button[contains(@class, 'o_form_button_save')]",
)
selenium_tool.click_with_mouse_move(
by=By.XPATH,
value="//h4[contains(text(), 'Créer Model')]/../../footer/button[contains(@class, 'o_form_button_save')]",
)
time.sleep(1)
selenium_tool.click_with_mouse_move(
by=By.XPATH,
value="//footer/div[@name='states_buttons']/button[@name='action_code_module_generate']",
)
# selenium_tool.click(
# "/html/body/header/nav/div/div[1]/div[2]/div/div/div/ul/li[2]/a",
# )
# selenium_tool.click(
# "/html/body/div[1]/main/div[2]/div/div/table/tbody/tr[1]/td[2]",
# )
# if config.open_me_devops_auto:
# selenium_tool.click(
# "/html/body/header/nav/div/div[1]/div[2]/div/div/div/ul/li[2]/a",
# )
# selenium_tool.click(
# "/html/body/div[1]/main/div[2]/div/div/table/tbody/tr[1]/td[2]",
# )
#
# # CG self
# # Bouton modifier
# # selenium_tool.click(
# # "/html/body/div[1]/main/div[1]/div[2]/div/div/div[1]/button[1]",
# # )
# # Tab Code
# # selenium_tool.click(
# # "/html/body/div[1]/main/div[2]/div/div/div[7]/ul/li[2]/a",
# # )
# # Bouton Plan
# selenium_tool.click(
# "/html/body/div[1]/main/div[2]/div/div/div[1]/div/button[1]",
# )
#
# # Bouton autopoiesis
# selenium_tool.click(
# "/html/body/div[4]/div/div/main/div/div/div[5]/table[2]/tbody/tr[2]/td[1]/button",
# )
#
# # Bouton devops regenerate
# selenium_tool.click(
# "/html/body/div[4]/div/div/main/div/div/div[6]/table[2]/tbody/tr[2]/td/button",
# )
#
# if config.open_me_devops_auto_force:
# # Disable «Stop Execution if Env Not Clean
# # selenium_tool.click(
# # "/html/body/div[1]/main/div[2]/div/div/div[7]/div/div[2]/div[6]/table[2]/tbody/tr[3]/td[2]/div/label",
# # )
# # Option Force Generate
# selenium_tool.click(
# "/html/body/div[4]/div/div/main/div/div/div[8]/table/tbody/tr[2]/td[1]/label",
# )
#
# # Gen
# # selenium_tool.click(
# # "/html/body/div[1]/main/div[2]/div/div/div[7]/div/div[2]/div[2]/table[1]/tbody/tr/td[1]/button",
# # )
#
# # Next state
# selenium_tool.click(
# "/html/body/div[4]/div/div/footer/div/footer/div/button[1]",
# )
#
# # Check error
# # selenium_tool.click(
# # "/html/body/div[1]/main/div[2]/div/div/div[7]/ul/li[13]/a",
# # )
# # selenium_tool.click("/html/body/div[1]/main/div[2]/div/div/div[6]/div/div[14]/div/div[2]/table/tbody/tr[1]", timeout=60*2)
def fill_parser(parser):
group_devops = parser.add_argument_group(title="DevOps")
group_devops.add_argument(
"--open_me_devops",
action="store_true",
help="Open application devops and show entry me.",
)
group_devops.add_argument(
"--open_me_devops_auto",
action="store_true",
help="Open application devops and show entry me and run auto setup.",
)
group_devops.add_argument(
"--open_me_devops_auto_force",
action="store_true",
help=(
"Open application devops and show entry me and run auto setup with"
" forcing argument."
),
)
group_devops.add_argument(
"--generate_code",
action="store_true",
help=("Open wizard to generate code"),
)
def compute_args(args):
if args.open_me_devops_auto_force:
args.open_me_devops_auto = True
args.open_me_devops = True
elif args.open_me_devops_auto:
args.open_me_devops = True
def main():
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description="""Selenium script to open web browser to ERPLibre adapted for ORE.""",
)
# Generate parser
selenium_lib.fill_parser(parser)
web_login.fill_parser(parser)
fill_parser(parser)
args = parser.parse_args()
web_login.compute_args(args)
compute_args(args)
# Instance selenium tool
selenium_tool = selenium_lib.SeleniumLib(args)
selenium_tool.configure()
selenium_tool.start_record()
# Execute
web_login.run(args, selenium_tool)
run(args, selenium_tool)
selenium_tool.stop_record()
return 0
if __name__ == "__main__":
sys.exit(main())

View file

@ -1,133 +0,0 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse
import sys
import selenium_lib
import web_login
def run(config, selenium_tool):
if config.open_me_devops:
selenium_tool.click(
"/html/body/header/nav/div/div[1]/div[2]/div/div/div/ul/li[2]/a",
)
selenium_tool.click(
"/html/body/div[1]/main/div[2]/div/div/table/tbody/tr[1]/td[2]",
)
if config.open_me_devops_auto:
selenium_tool.click(
"/html/body/header/nav/div/div[1]/div[2]/div/div/div/ul/li[2]/a",
)
selenium_tool.click(
"/html/body/div[1]/main/div[2]/div/div/table/tbody/tr[1]/td[2]",
)
# CG self
# Bouton modifier
# selenium_tool.click(
# "/html/body/div[1]/main/div[1]/div[2]/div/div/div[1]/button[1]",
# )
# Tab Code
# selenium_tool.click(
# "/html/body/div[1]/main/div[2]/div/div/div[7]/ul/li[2]/a",
# )
# Bouton Plan
selenium_tool.click(
"/html/body/div[1]/main/div[2]/div/div/div[1]/div/button[1]",
)
# Bouton autopoiesis
selenium_tool.click(
"/html/body/div[4]/div/div/main/div/div/div[5]/table[2]/tbody/tr[2]/td[1]/button",
)
# Bouton devops regenerate
selenium_tool.click(
"/html/body/div[4]/div/div/main/div/div/div[6]/table[2]/tbody/tr[2]/td/button",
)
if config.open_me_devops_auto_force:
# Disable «Stop Execution if Env Not Clean
# selenium_tool.click(
# "/html/body/div[1]/main/div[2]/div/div/div[7]/div/div[2]/div[6]/table[2]/tbody/tr[3]/td[2]/div/label",
# )
# Option Force Generate
selenium_tool.click(
"/html/body/div[4]/div/div/main/div/div/div[8]/table/tbody/tr[2]/td[1]/label",
)
# Gen
# selenium_tool.click(
# "/html/body/div[1]/main/div[2]/div/div/div[7]/div/div[2]/div[2]/table[1]/tbody/tr/td[1]/button",
# )
# Next state
selenium_tool.click(
"/html/body/div[4]/div/div/footer/div/footer/div/button[1]",
)
# Check error
# selenium_tool.click(
# "/html/body/div[1]/main/div[2]/div/div/div[7]/ul/li[13]/a",
# )
# selenium_tool.click("/html/body/div[1]/main/div[2]/div/div/div[6]/div/div[14]/div/div[2]/table/tbody/tr[1]", timeout=60*2)
def fill_parser(parser):
group_devops = parser.add_argument_group(title="DevOps")
group_devops.add_argument(
"--open_me_devops",
action="store_true",
help="Open application devops and show entry me.",
)
group_devops.add_argument(
"--open_me_devops_auto",
action="store_true",
help="Open application devops and show entry me and run auto setup.",
)
group_devops.add_argument(
"--open_me_devops_auto_force",
action="store_true",
help=(
"Open application devops and show entry me and run auto setup with"
" forcing argument."
),
)
def compute_args(args):
if args.open_me_devops_auto_force:
args.open_me_devops_auto = True
args.open_me_devops = True
elif args.open_me_devops_auto:
args.open_me_devops = True
def main():
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description="""Selenium script to open web browser to ERPLibre adapted for ORE.""",
)
# Generate parser
selenium_lib.fill_parser(parser)
web_login.fill_parser(parser)
fill_parser(parser)
args = parser.parse_args()
web_login.compute_args(args)
compute_args(args)
# Instance selenium tool
selenium_tool = selenium_lib.SeleniumLib(args)
selenium_tool.configure()
selenium_tool.start_record()
# Execute
web_login.run(args, selenium_tool)
run(args, selenium_tool)
selenium_tool.stop_record()
return 0
if __name__ == "__main__":
sys.exit(main())

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import datetime
@ -35,6 +35,11 @@ from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select, WebDriverWait
new_path = os.path.normpath(
os.path.join(os.path.dirname(__file__), "..", "..")
)
sys.path.append(new_path)
from script.config import config_file
logging.basicConfig(
@ -253,9 +258,12 @@ class SeleniumLib(object):
firefox_options.set_preference("pdfjs.disabled", True)
if self.config.window_size:
# chrome_options.add_argument("--window-size=1920,1080")
firefox_options.add_argument(
f"--window-size={self.config.window_size}"
)
# firefox_options.add_argument(
# f"--window-size={self.config.window_size}"
# )
width, height = self.config.window_size.split(",")
firefox_options.add_argument("--width=" + str(width))
firefox_options.add_argument("--height=" + str(height))
if self.config.headless:
firefox_options.add_argument("--headless")

View file

@ -10,6 +10,9 @@ try:
except ImportError:
print("Please read installation script/selenium/install.md")
raise
except ModuleNotFoundError:
print("Please read installation script/selenium/install.md")
raise
Gst.init(None)

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse
@ -97,7 +97,10 @@ def main():
# Default paths and fallback values (same logic as in the bash script)
el_user = args.user
el_home_erplibre = args.home_erplibre or os.getcwd()
el_config_name = args.config_name or f"erplibre_{el_user}_{os.path.basename(os.getcwd())}"
el_config_name = (
args.config_name
or f"erplibre_{el_user}_{os.path.basename(os.getcwd())}"
)
exec_param = (
" "
+ f" {w_cmd("-d", args.database or "")} {w_cmd("-p", args.port or "")}".strip()

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# © 2021-2024 TechnoLibre (http://www.technolibre.ca)
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
# This script need only basic importation, it needs to be supported by python of your system