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 all Makefile
-include ./conf/make.code_generator.Makefile -include ./conf/make.code_generator.Makefile
-include ./conf/make.robotlibre.Makefile
-include ./conf/make.erplibre.Makefile -include ./conf/make.erplibre.Makefile
-include ./conf/make.database.Makefile -include ./conf/make.database.Makefile
-include ./conf/make.docker.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 name,script_path,parameters,folder,default
run,./odoo/odoo-bin,--limit-time-real 999999 -c config.conf,run,True run,./odoo/odoo-bin,--limit-time-real 999999 -c config.conf,run,True
run_parallel_test,./script/test/run_parallel_test.py,,test, 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,./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, cg_cg_template,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d template -i code_generator_template_code_generator,code_generator_template,
code_generator_auto_backup,./odoo/odoo-bin,--limit-time-real 999999 --no-http -c config.conf --stop-after-init --dev cg -d code_generator -i code_generator_auto_backup,code_generator, code_generator_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 restart: always
db: db:
image: postgis/postgis:18-3.6-alpine image: postgis/postgis:17-3.6-alpine
environment: environment:
POSTGRES_PASSWORD: mysecretpassword POSTGRES_PASSWORD: mysecretpassword
POSTGRES_USER: odoo POSTGRES_USER: odoo
POSTGRES_DB: postgres POSTGRES_DB: postgres
PGDATA: /var/lib/postgresql/pgdata PGDATA: /var/lib/postgresql/data/pgdata
volumes: volumes:
- erplibre-db-data:/var/lib/postgresql/pgdata - erplibre-db-data:/var/lib/postgresql/data/pgdata
restart: always restart: always
# We configure volume without specific destination to let docker manage it. To configure it through docker use (read related documentation before continuing) : # 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 restart: always
db: db:
image: postgis/postgis:18-3.6-alpine image: postgis/postgis:17-3.6-alpine
environment: environment:
POSTGRES_PASSWORD: mysecretpassword POSTGRES_PASSWORD: mysecretpassword
POSTGRES_USER: odoo POSTGRES_USER: odoo
POSTGRES_DB: postgres POSTGRES_DB: postgres
PGDATA: /var/lib/postgresql/pgdata PGDATA: /var/lib/postgresql/data/pgdata
volumes: volumes:
- erplibre-db-data:/var/lib/postgresql/pgdata - erplibre-db-data:/var/lib/postgresql/data/pgdata
restart: always restart: always
# We configure volume without specific destination to let docker manage it. To configure it through docker use (read related documentation before continuing) : # 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 restart: always
db: db:
image: postgis/postgis:18-3.6-alpine image: postgis/postgis:17-3.6-alpine
environment: environment:
POSTGRES_PASSWORD: mysecretpassword POSTGRES_PASSWORD: mysecretpassword
POSTGRES_USER: odoo POSTGRES_USER: odoo
POSTGRES_DB: postgres POSTGRES_DB: postgres
PGDATA: /var/lib/postgresql/pgdata PGDATA: /var/lib/postgresql/data/pgdata
volumes: volumes:
- erplibre-db-data:/var/lib/postgresql/pgdata - erplibre-db-data:/var/lib/postgresql/data/pgdata
restart: always restart: always
chrome: chrome:

View file

@ -1,29 +1,34 @@
#!/usr/bin/env python #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse
from os import listdir
from os.path import isdir, join, abspath
import configparser 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("addonsBaseDir", help="Path where addons are cloned.")
parser.add_argument("srcConfigPath", parser.add_argument(
help="Path where we retrieve source config file to adapt with new " "srcConfigPath",
"addons path.") help="Path where we retrieve source config file to adapt with new "
parser.add_argument("dstConfigPath", help="Path to save adapted configuration.") "addons path.",
)
parser.add_argument(
"dstConfigPath", help="Path to save adapted configuration."
)
args = parser.parse_args() args = parser.parse_args()
addonsBaseDir = args.addonsBaseDir addonsBaseDir = args.addonsBaseDir
srcConfigPath = args.srcConfigPath srcConfigPath = args.srcConfigPath
dstConfigPath = args.dstConfigPath dstConfigPath = args.dstConfigPath
addonsDirs = [abspath(join(addonsBaseDir, f)) for f in listdir(addonsBaseDir) if addonsDirs = [
isdir(join(addonsBaseDir, f))] abspath(join(addonsBaseDir, f))
for f in listdir(addonsBaseDir)
if isdir(join(addonsBaseDir, f))
]
with open(".odoo-version", "r") as f: with open(".odoo-version", "r") as f:
odoo_version = f.readline().strip() odoo_version = f.readline().strip()
@ -39,9 +44,9 @@ config.read(srcConfigPath)
separator = "," 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) config.write(configfile)

View file

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

View file

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

View file

@ -236,10 +236,14 @@ description = "Read/rewrite/write Python ASTs"
optional = false optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7"
groups = ["main"] groups = ["main"]
files = [ files = []
{file = "astor-0.8.1-py2.py3-none-any.whl", hash = "sha256:070a54e890cefb5b3739d19f30f5a5ec840ffc9c50ffa7d23cc9fc1a38ebbfc5"}, develop = false
{file = "astor-0.8.1.tar.gz", hash = "sha256:6a6effda93f4e1ce9f618779b2dd1d9d84f1e32812c23a29b3fff6fd7f63fa5e"},
] [package.source]
type = "git"
url = "https://github.com/berkerpeksag/astor.git"
reference = "HEAD"
resolved_reference = "df09001112f079db54e7c5358fa143e1e63e74c4"
[[package]] [[package]]
name = "astroid" name = "astroid"
@ -503,18 +507,18 @@ xyzservices = ">=2021.09.1"
[[package]] [[package]]
name = "boto3" name = "boto3"
version = "1.40.64" version = "1.40.67"
description = "The AWS SDK for Python" description = "The AWS SDK for Python"
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "boto3-1.40.64-py3-none-any.whl", hash = "sha256:35ca3dd80dd90d5f4e8ed032440f28790696fdf50f48c0d16a09a75675f9112f"}, {file = "boto3-1.40.67-py3-none-any.whl", hash = "sha256:3d06e9b3c7abedb8253c7d75b9ab27005480ca1e6e448d1f3c3cc3e209673ca0"},
{file = "boto3-1.40.64.tar.gz", hash = "sha256:b92d6961c352f2bb8710c9892557d4b0e11258b70967d4e740e1c97375bcd779"}, {file = "boto3-1.40.67.tar.gz", hash = "sha256:3e4317139ace6d44658b8e1f2b5b6612f05b45720721841c90cdee45b02aa514"},
] ]
[package.dependencies] [package.dependencies]
botocore = ">=1.40.64,<1.41.0" botocore = ">=1.40.67,<1.41.0"
jmespath = ">=0.7.1,<2.0.0" jmespath = ">=0.7.1,<2.0.0"
s3transfer = ">=0.14.0,<0.15.0" s3transfer = ">=0.14.0,<0.15.0"
@ -523,14 +527,14 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"]
[[package]] [[package]]
name = "botocore" name = "botocore"
version = "1.40.64" version = "1.40.67"
description = "Low-level, data-driven core of boto 3." description = "Low-level, data-driven core of boto 3."
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "botocore-1.40.64-py3-none-any.whl", hash = "sha256:6902b3dadfba1fbacc9648171bef3942530d8f823ff2bdb0e585a332323f89fc"}, {file = "botocore-1.40.67-py3-none-any.whl", hash = "sha256:e49e61f6718e8bc8b34e9bb8a97f16c8dc560485faef4981b55d76f825c9d78a"},
{file = "botocore-1.40.64.tar.gz", hash = "sha256:a13af4009f6912eafe32108f6fa584fb26e24375149836c2bcaaaaec9a7a9e58"}, {file = "botocore-1.40.67.tar.gz", hash = "sha256:cc086f39c877aee0ea8dc88ef69062c9f395b9d30d49bfcfac7b8b7e61864b3a"},
] ]
[package.dependencies] [package.dependencies]
@ -1241,84 +1245,51 @@ tests = ["pytest", "pytest-cov", "pytest-xdist"]
[[package]] [[package]]
name = "cython" name = "cython"
version = "3.1.6" version = "3.2.0"
description = "The Cython compiler for writing C extensions in the Python language." description = "The Cython compiler for writing C extensions in the Python language."
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "cython-3.1.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c4027b4d1bf7781fdfb2dbe1c1d81ccac9b910831511747e2c9fc8452fb3ea6b"}, {file = "cython-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ee408125b2d218ec7d7a061e09d24715fcab9bf7ea1a4ac01907c3f8ec8730b3"},
{file = "cython-3.1.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:141dea9df09f9c711af3b95510bd417c58b2abd33676eef1cb61f25581f7090a"}, {file = "cython-3.2.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c93ce307b05fcd86a5bb0e4a7d7fab238e2f0e9936636097a60bc0e21f2def30"},
{file = "cython-3.1.6-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:486376a988268408b7e8ea7b4cccffb914aa497c498b41589fb4a862ba47e050"}, {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.1.6-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bdc6e63a04ead11812752a5198b85b7fc079688c76712348d072403f18fdeb49"}, {file = "cython-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:a259053037ef82959b743b7fde238bd191ee43f88eb8e51101d5f3d8849f1e32"},
{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.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e9e4b2248dc3a98b86aeba65e9862d2cc881d072c163c0fb31b511d4d72e93c8"},
{file = "cython-3.1.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2379f729f1d5a445adb4621f279f7c23aeb6245f036f96cce14b5b2fd1f5ff0a"}, {file = "cython-3.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:02fb4990a83d5d6f780dda18ed8baa8d587cb6523f57b4d72bc0b41ad3766c96"},
{file = "cython-3.1.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1089e18d938b6e742f077e398d52e1701080213c4f203755afde6f1b33d9e051"}, {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.1.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:73576246abbc62397db85cbdde74d2e5d73dabfdb7e593fdbb3671275ffb50ce"}, {file = "cython-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:4c959a5d4cd6331e8498822ba47200bd2ff4bf74517c0c91475d5bc21da3b4d5"},
{file = "cython-3.1.6-cp310-cp310-win32.whl", hash = "sha256:f48eae3275b3352ba7eb550fc5321b0fb1ba8d916fa9985fb2f02ce42ae69ddd"}, {file = "cython-3.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:511d823d9f8a1b850178ec355d6df0a1731b9c20b08ee6d1a780f68215e9013f"},
{file = "cython-3.1.6-cp310-cp310-win_amd64.whl", hash = "sha256:4066908ee24a18572880966de1d0865d178f5ab9828a9249faa97e1ffdfbed9f"}, {file = "cython-3.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bbadeedcb2d135655bcce7380fb28c9e2a75b6810426c12b6e5a6fe6106fafb4"},
{file = "cython-3.1.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5a1aedd8990f470d108b76ca768d9f1766d6610cf2546b73075dbe1e523daebe"}, {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.1.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f75c33e83e224737b1a68b2868bc08bddaabc6f04aef74864ff6069fe2e68341"}, {file = "cython-3.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:73435e56654a34ece57d4c3304a4556a8402cc4ae2d0e30f71c237a985dc5246"},
{file = "cython-3.1.6-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:91b8fb3e961b3344bf257b851f2ce679727f44857fec94d643bcc458601dab54"}, {file = "cython-3.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d900e58e826f9a5a27b0e2b50e33473e9986a5bae375c39b0f2e19f2c545fa23"},
{file = "cython-3.1.6-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1cfeb04d43464f5ff8398b499ba46c6eef22093da0e74b25f972576e768880e7"}, {file = "cython-3.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a9d38cd3aab720d21fa6d6ee168228352f69aea0a95bd4fb84e8879c6ed38fbb"},
{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.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:92b31d0b7b0a49b3d2aa94faaf75d44a03174cff2616b341a8853c919e511d51"},
{file = "cython-3.1.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9856e8cd7f7a95a3f10a8f15fef4d17e5a4a57fb5185fe3482cec4adb0536635"}, {file = "cython-3.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:2847b74e76dbad612f6fc7182c12a5f78cffb0d05808fd2c4b638cf02d1aade6"},
{file = "cython-3.1.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6966f4d4ee13eceade2d952dc63bdf313f413c0c3f165aef0d6f62e6f27dab02"}, {file = "cython-3.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a0a8274959d538d12f865193dcd67bb5630906e020190c890d2b7c13d31713c6"},
{file = "cython-3.1.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dffb14bc986626be50003f4edc614a2c0a56cbaaf87259f6c763a6d21da14921"}, {file = "cython-3.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a1c800833c25195833805c7c3626a2c30b3baaaa9ba361a1af3bbc379662a8d"},
{file = "cython-3.1.6-cp311-cp311-win32.whl", hash = "sha256:cde4748d37483b6c91df9f4327768e2828b1e374cb61bcee06d618958de59b7b"}, {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.1.6-cp311-cp311-win_amd64.whl", hash = "sha256:29d6141b0c9697dfcaf5940eceb06353bec76f51f0579658964c0d29418000df"}, {file = "cython-3.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:9d6876af2132757fff1b42a2f4eaa72482f991863160e3f0dc8f2c812b300ebf"},
{file = "cython-3.1.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0d2c32e8f6c65854e8203b381ff7ab540820763756b7c326e2c8dc18c9bbb44e"}, {file = "cython-3.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d41c8c3d4a98f151ec11b80e5aa865fce0cec2b5c7f49ed477e06d6aa03fe17c"},
{file = "cython-3.1.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:be24fcde7300a81712af279467ebc79baafc8483eb4dfa4daebf8ee90a826d39"}, {file = "cython-3.2.0-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:acc01538767f9bd467494860f0ec0644d6f6ba5bd768b7f14d7b404a459b19fa"},
{file = "cython-3.1.6-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5012025af433bd7188fe1f7705df1c4a67e7add80c71658f6c6bc35ea876cc68"}, {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.1.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3b3520e2d4484f927c3ec00d32ffda75ec72cfd6a2ee07adac721cce339fa26f"}, {file = "cython-3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:b8461df22d8ea1233eceeaf329d359c8870023f48515209eb0b79902583f7207"},
{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.2.0-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:04821ce06598a3aa5c9e0270d98960cfe6556dedbd1418c65e4479162b8ae74a"},
{file = "cython-3.1.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:fd88799fa7bb177182423e0745c9197c50938c6839ebfbe6fd01539582ed488e"}, {file = "cython-3.2.0-cp39-abi3-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:54b5b1c72a63da822b3f4739a0e31546c0a19f8e834b174906bf817ed5f9d65f"},
{file = "cython-3.1.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:f809bae2e00b79c01ff5daf9a260df7c1bc9fda087b9d625592fa28c1a2248a9"}, {file = "cython-3.2.0-cp39-abi3-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6155a6c360e32af1aaa16fa10b0119b49deeadff42a1958973324150870af1b5"},
{file = "cython-3.1.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6f657e7a4b2242d159de603f280928d8e458dfba48144714774ad76c08f5a530"}, {file = "cython-3.2.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:861258ac3878b76c57b9b5a379787d772a0bc47fec9167b43986777de542c474"},
{file = "cython-3.1.6-cp312-cp312-win32.whl", hash = "sha256:6502f3e58db0ab3e2c983bec2c8c9e45d602e2c7ff921a5a8515b0008d918102"}, {file = "cython-3.2.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:85dbf955e3193893d0288105afa0fa5f4e835ff587061681f240a4f0487c44fb"},
{file = "cython-3.1.6-cp312-cp312-win_amd64.whl", hash = "sha256:71d099d8d6094c5de63a32e67b29964565aed889a218e8d16a94083f4239b904"}, {file = "cython-3.2.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:3b3f13822526726bac43275c0e92916bbcc2c30e9f559edc4c1132670b70498d"},
{file = "cython-3.1.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:14f0d6b9f803eacf48e9e80ea12a03f54e5f5ac48914341b0a6b81554b3b3154"}, {file = "cython-3.2.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ab18d09673d219008be5b6174bcbb6dbfd50904e66371f104a8a4698b791472d"},
{file = "cython-3.1.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ec79615d0e29fa29fd4283bc7a2ed9c3d00532086a0031532d64b724db8c3e8e"}, {file = "cython-3.2.0-cp39-abi3-win32.whl", hash = "sha256:c9fd986413fc52929b916187630a9abab9f876299951488c4b905ad5346afee6"},
{file = "cython-3.1.6-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:037d457738cf4fc12260946c6524b745f488cf413428099f2a064af7612d181f"}, {file = "cython-3.2.0-cp39-abi3-win_arm64.whl", hash = "sha256:ee2ea79ddeb721f912e7efea039b9db059c81767ff04fbf9a995f64e1187df99"},
{file = "cython-3.1.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b036cb4ed7abcbc89cc04311832b22ad386c532fdd1fe690e1364aa992a54c7"}, {file = "cython-3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b6e5df85f6dca0ccad0d86f7517d70653d74fcd9e739fc5eb8fb23312f07b73d"},
{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.2.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eba59b55e9d743b5b62a57cef942688c1f52e09632ea6f25b3bbe6c47ecc2db2"},
{file = "cython-3.1.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92eb7a39e60426165a5b2a219af181e5695c4dedd598e317a7a4d9086bd66b91"}, {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.1.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c475018b28f4e7111148bd02b600595090e0aac6cc49615c4586bb4e7f164a22"}, {file = "cython-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:9b54abd3dfd2bf43fdcba1a27fcfe1012a4b196ab77d7fd20fb97942d1ac0ed5"},
{file = "cython-3.1.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b1b4bb661103cb95c6ca70daf5d39992b2d89fd260b02a54d92e365095ed37eb"}, {file = "cython-3.2.0-py3-none-any.whl", hash = "sha256:73f7f4c75acde5b5b4df05b11fdc2705ec637b99241d1bc2f4ebf345f7a2ea90"},
{file = "cython-3.1.6-cp313-cp313-win32.whl", hash = "sha256:69b1bea23b51628b8c9f14c3e0bb4c7dd5be63781bfbaa581b1c683b473c728a"}, {file = "cython-3.2.0.tar.gz", hash = "sha256:41fdce8237baee2d961c292ed0386903dfe126f131e450a62de0fd7a5280d4b2"},
{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"},
] ]
[[package]] [[package]]
@ -2470,22 +2441,20 @@ files = [
[[package]] [[package]]
name = "img2pdf" name = "img2pdf"
version = "0.6.1" version = "0.6.3"
description = "Convert images to PDF via direct JPEG inclusion." description = "Lossless conversion of raster images to PDF."
optional = false optional = false
python-versions = "*" python-versions = ">=3.5"
groups = ["main"] groups = ["main"]
files = [ 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] [package.dependencies]
pikepdf = "*" pikepdf = "*"
Pillow = "*" Pillow = "*"
[package.extras]
gui = ["tkinter"]
[[package]] [[package]]
name = "iso3166" name = "iso3166"
version = "2.1.1" version = "2.1.1"
@ -3696,6 +3665,31 @@ files = [
{file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, {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]] [[package]]
name = "nextcloud-api-wrapper" name = "nextcloud-api-wrapper"
version = "0.2.3" version = "0.2.3"
@ -3932,14 +3926,14 @@ full = ["XLMMacroDeobfuscator"]
[[package]] [[package]]
name = "openai" name = "openai"
version = "2.6.1" version = "2.7.1"
description = "The official Python library for the openai API" description = "The official Python library for the openai API"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "openai-2.6.1-py3-none-any.whl", hash = "sha256:904e4b5254a8416746a2f05649594fa41b19d799843cd134dac86167e094edef"}, {file = "openai-2.7.1-py3-none-any.whl", hash = "sha256:2f2530354d94c59c614645a4662b9dab0a5b881c5cd767a8587398feac0c9021"},
{file = "openai-2.6.1.tar.gz", hash = "sha256:27ae704d190615fca0c0fc2b796a38f8b5879645a3a52c9c453b23f97141bb49"}, {file = "openai-2.7.1.tar.gz", hash = "sha256:df4d4a3622b2df3475ead8eb0fbb3c27fd1c070fa2e55d778ca4f40e0186c726"},
] ]
[package.dependencies] [package.dependencies]
@ -3975,14 +3969,14 @@ et-xmlfile = "*"
[[package]] [[package]]
name = "openupgradelib" name = "openupgradelib"
version = "3.11.1" version = "3.12.0"
description = "A library with support functions to be called from Odoo migration scripts." description = "A library with support functions to be called from Odoo migration scripts."
optional = false optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "openupgradelib-3.11.1-py2.py3-none-any.whl", hash = "sha256:e34c57c835e6434171ceebe00d4a6b3245351135c602b39b868d7f82912efc56"}, {file = "openupgradelib-3.12.0-py2.py3-none-any.whl", hash = "sha256:f8f624f4863b2257f760a9959ddd3cfee650b8f4a8740610506c4473ed36b679"},
{file = "openupgradelib-3.11.1.tar.gz", hash = "sha256:b37adbf37b94e649febb99eaa887ee218c3b372061087e35e3901af585d8cbed"}, {file = "openupgradelib-3.12.0.tar.gz", hash = "sha256:3f3cd2475f7eb387fb0c364b7d2828b268dcf6e9c83aecccfbfe5c76cc69e4d7"},
] ]
[package.dependencies] [package.dependencies]
@ -4214,6 +4208,21 @@ files = [
[package.dependencies] [package.dependencies]
pycryptodome = "*" 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]] [[package]]
name = "phonenumbers" name = "phonenumbers"
version = "9.0.17" 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)"] 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)"] 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]] [[package]]
name = "ply" name = "ply"
version = "3.11" version = "3.11"
@ -4652,6 +4685,18 @@ files = [
{file = "psycopg2-2.9.9.tar.gz", hash = "sha256:d1454bde93fb1e224166811694d600e746430c006fbb031ea06ecc2ea41bf156"}, {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]] [[package]]
name = "py3dns" name = "py3dns"
version = "4.0.2" version = "4.0.2"
@ -5181,62 +5226,19 @@ pylint = ">=1.7"
[[package]] [[package]]
name = "pymssql" 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)" description = "DB-API interface to Microsoft SQL Server for Python. (new Cython-based version)"
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
groups = ["main"] groups = ["main"]
files = [ files = []
{file = "pymssql-2.3.8-cp310-cp310-macosx_13_0_x86_64.whl", hash = "sha256:529c972bfc907baff8f30d9d397471c2786a3293a849490f908c6c79b0687c73"}, develop = false
{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"}, [package.source]
{file = "pymssql-2.3.8-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d0f3e2df22e5d73add12613c764bbb5fe7d26119c9cb2aa9de311f514a0060eb"}, type = "git"
{file = "pymssql-2.3.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:bdc738cfae0889940cffd51bb4e45589ddf42c6464ca570dd5982b2b1defc70b"}, url = "https://github.com/pymssql/pymssql.git"
{file = "pymssql-2.3.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e3dff5e1523de22a8fa5c304c9c262e56ef28207c6e2551fe2aff8395f03b459"}, reference = "HEAD"
{file = "pymssql-2.3.8-cp310-cp310-win32.whl", hash = "sha256:d3bd82ce1b42ae95e0da06b861a31b3c946bdac1ead0226f72a18f4f7eced136"}, resolved_reference = "da1ef7e5623ef262dd0e4fbc2119106ca8f7e41e"
{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"},
]
[[package]] [[package]]
name = "pymysql" name = "pymysql"
@ -5469,20 +5471,20 @@ certifi = "*"
[[package]] [[package]]
name = "pyrdfa3" name = "pyrdfa3"
version = "3.6.4" version = "3.6.2"
description = "pyRdfa distiller/parser library" description = "pyRdfa distiller/parser library"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.7"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "pyRdfa3-3.6.4-py3-none-any.whl", hash = "sha256:ed11affa5567ab7afdbc939a58f9286a274447f3ab2999c260c56b5c6e87fb2f"}, {file = "pyRdfa3-3.6.2-py3-none-any.whl", hash = "sha256:290c2fa966ddd1b45ac94a727da144f5a233ed58c63c370e3d68e6d00b0dee5d"},
{file = "pyrdfa3-3.6.4.tar.gz", hash = "sha256:64712d1a4bf21829652b39715bada6e7c03bcf19cb49f962c190a38f46172243"}, {file = "pyRdfa3-3.6.2.tar.gz", hash = "sha256:73681dab957f60901696767388b956a5769c730bc451da6ffb2f0e36f18314c2"},
] ]
[package.dependencies] [package.dependencies]
html5lib = ">=1.1" html5lib = ">=1.1"
rdflib = ">=7.0.0" rdflib = ">=6.1.1"
requests = ">=2.32.3" requests = ">=2.25.1"
[[package]] [[package]]
name = "pysaml2" name = "pysaml2"
@ -5653,6 +5655,24 @@ files = [
pyasn1 = ">=0.3.7" pyasn1 = ">=0.3.7"
pyasn1_modules = ">=0.1.5" 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]] [[package]]
name = "python-resize-image" name = "python-resize-image"
version = "1.1.20" version = "1.1.20"
@ -6551,6 +6571,28 @@ webencodings = ">=0.4"
doc = ["sphinx", "sphinx_rtd_theme"] doc = ["sphinx", "sphinx_rtd_theme"]
test = ["pytest", "ruff"] 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]] [[package]]
name = "tomlkit" name = "tomlkit"
version = "0.13.3" 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)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
zstd = ["zstandard (>=0.18.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]] [[package]]
name = "validate-email" name = "validate-email"
version = "1.3" version = "1.3"
@ -7351,4 +7457,4 @@ bindings = ["ghostscript"]
[metadata] [metadata]
lock-version = "2.1" lock-version = "2.1"
python-versions = ">=3.12.10,<3.13" 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] [tool.poetry.dependencies]
python = ">=3.12.10,<3.13" python = ">=3.12.10,<3.13"
asn1crypto = "1.5.1" asn1crypto = "1.5.1"
astor = "^0.8.1"
avalara = "^25.9.0" avalara = "^25.9.0"
babel = "2.10.3" babel = "2.10.3"
bandit = "^1.8.6" bandit = "^1.8.6"
base64io = "^1.0.3" base64io = "^1.0.3"
beautifulsoup4 = "4.13.5" beautifulsoup4 = "4.13.5"
bokeh = "3.6.3" bokeh = "3.6.3"
boto3 = "^1.40.64" boto3 = "^1.40.67"
cachetools = "^6.2.1" cachetools = "^6.2.1"
cairosvg = "^2.8.2" cairosvg = "^2.8.2"
caldav = "1.3.9" caldav = "1.3.9"
cbor2 = "5.6.2" cbor2 = "5.6.2"
chardet = "5.2.0" chardet = "5.2.0"
code-writer = "^1.2.0" code-writer = "^1.2.0"
colorama = "^0.4.6"
cryptography = "46.0.3" cryptography = "46.0.3"
cssselect = "^1.3.0" cssselect = "^1.3.0"
cython = "^3.1.6" cython = "^3.2.0"
decorator = "5.1.1" decorator = "5.1.1"
docutils = "0.20.1" docutils = "0.20.1"
dropbox = "^12.0.2" dropbox = "^12.0.2"
@ -59,7 +59,7 @@ greenlet = "3.0.3"
httpagentparser = "^1.9.5" httpagentparser = "^1.9.5"
icalendar = "5.0.13" icalendar = "5.0.13"
idna = "3.6" idna = "3.6"
img2pdf = "^0.6.1" img2pdf = "^0.6.3"
isort = "6.1.0" isort = "6.1.0"
jinja2 = "3.1.2" jinja2 = "3.1.2"
js2py = "^0.74" js2py = "^0.74"
@ -81,9 +81,9 @@ num2words = "0.5.13"
numpy-stl = "^3.2.0" numpy-stl = "^3.2.0"
odoorpc = "^0.10.1" odoorpc = "^0.10.1"
ofxparse = "0.21" ofxparse = "0.21"
openai = "^2.6.1" openai = "^2.7.1"
openpyxl = "3.1.2" openpyxl = "3.1.2"
openupgradelib = "^3.11.1" openupgradelib = "^3.12.0"
openwebui-client = ">=0.3.0" openwebui-client = ">=0.3.0"
pandas = ">=0.25.3" pandas = ">=0.25.3"
paramiko = "<4.0.0" paramiko = "<4.0.0"
@ -91,8 +91,10 @@ passlib = "1.7.4"
pathspec = "^0.12.1" pathspec = "^0.12.1"
pdf2image = "^1.17.0" pdf2image = "^1.17.0"
pdfminer = "^20191125" pdfminer = "^20191125"
pexpect = "^4.9.0"
phonenumbers = "^9.0.17" phonenumbers = "^9.0.17"
pillow = "10.2.0" pillow = "10.2.0"
plotly = "^6.4.0"
polib = "1.1.1" polib = "1.1.1"
pre-commit = "^4.3.0" pre-commit = "^4.3.0"
premailer = "^3.10.0" premailer = "^3.10.0"
@ -110,7 +112,6 @@ pyjsparser = "^2.7.1"
pyjwt = "^2.10.1" pyjwt = "^2.10.1"
pylint = "3.3.9" pylint = "3.3.9"
pylint-odoo = "^9.3.22" pylint-odoo = "^9.3.22"
pymssql = "^2.3.8"
pymysql = "^1.1.2" pymysql = "^1.1.2"
pyncclient = "^0.7" pyncclient = "^0.7"
pyopenssl = "25.3.0" pyopenssl = "25.3.0"
@ -125,6 +126,7 @@ python-dotenv = ">=1.0.0"
python-jose = "^3.5.0" python-jose = "^3.5.0"
python-json-logger = "^4.0.0" python-json-logger = "^4.0.0"
python-ldap = "3.4.4" python-ldap = "3.4.4"
python-pptx = "^1.0.2"
python-resize-image = "^1.1.20" python-resize-image = "^1.1.20"
python-slugify = "^8.0.4" python-slugify = "^8.0.4"
python-stdnum = "1.19" python-stdnum = "1.19"
@ -148,10 +150,12 @@ sentry-sdk = ">=2.0.0,<=2.22.0"
setuptools = "80.9.0" setuptools = "80.9.0"
shapely = "^2.1.2" shapely = "^2.1.2"
statsd = "^4.0.1" statsd = "^4.0.1"
tldextract = "^5.3.0"
tweepy = "^4.16.0" tweepy = "^4.16.0"
twilio = "^9.8.5" twilio = "^9.8.5"
unidecode = "^1.4.0" unidecode = "^1.4.0"
urllib3 = "2.0.7" urllib3 = "2.0.7"
uvloop = "^0.22.1"
validate-email = "^1.3" validate-email = "^1.3"
vobject = "0.9.6.1" vobject = "0.9.6.1"
w3lib = "^2.3.1" w3lib = "^2.3.1"
@ -163,6 +167,9 @@ xlwt = "1.3.0"
xmltodict = "0.13.0" xmltodict = "0.13.0"
zeep = "4.2.1" zeep = "4.2.1"
[tool.poetry.dependencies.astor]
git = "https://github.com/berkerpeksag/astor.git"
[tool.poetry.dependencies.black] [tool.poetry.dependencies.black]
git = "https://github.com/psf/black.git" git = "https://github.com/psf/black.git"
rev = "24.8.0" rev = "24.8.0"
@ -171,6 +178,9 @@ rev = "24.8.0"
extras = [ "s3",] extras = [ "s3",]
version = "^2025.10.0" version = "^2025.10.0"
[tool.poetry.dependencies.pymssql]
git = "https://github.com/pymssql/pymssql.git"
[tool.poetry.dependencies.pysaml2] [tool.poetry.dependencies.pysaml2]
git = "https://github.com/prauscher/pysaml2.git" git = "https://github.com/prauscher/pysaml2.git"
rev = "replace-pyopenssl" rev = "replace-pyopenssl"

View file

@ -64,3 +64,9 @@ cryptography==46.0.3
pyopenssl==25.3.0 pyopenssl==25.3.0
# This will ignore pyopenssl from pysaml2==7.5.4 # This will ignore pyopenssl from pysaml2==7.5.4
git+https://github.com/prauscher/pysaml2.git@replace-pyopenssl 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 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

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

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,40 +1,48 @@
#!/usr/bin/env python3 #!/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) # 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 logging
import sys
from pathlib import Path from pathlib import Path
ODOO_URL = '' # Your Odoo server URL import requests
DATABASE_NAME = ''
MASTER_PASSWORD = '' ODOO_URL = "" # Your Odoo server URL
DATABASE_NAME = ""
MASTER_PASSWORD = ""
# BACKUP_FORMAT = env('BACKUP_FORMAT', default='zip') # 'zip' or 'dump' # BACKUP_FORMAT = env('BACKUP_FORMAT', default='zip') # 'zip' or 'dump'
BACKUP_FORMAT = 'zip' # 'zip' or 'dump' BACKUP_FORMAT = "zip" # 'zip' or 'dump'
OUTPUT_FILE_NAME = f'{DATABASE_NAME}_backup.{BACKUP_FORMAT}' OUTPUT_FILE_NAME = f"{DATABASE_NAME}_backup.{BACKUP_FORMAT}"
# --- Logger Setup --- # --- Logger Setup ---
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# TODO not working with remote, only localhost # 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 --- # --- Function to download the database ---
def download_odoo_db(): 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 # 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 # Form data for the POST request
payload = { payload = {
'master_pwd': MASTER_PASSWORD, "master_pwd": MASTER_PASSWORD,
'name': DATABASE_NAME, "name": DATABASE_NAME,
'backup_format': BACKUP_FORMAT, "backup_format": BACKUP_FORMAT,
} }
try: try:
@ -43,20 +51,28 @@ def download_odoo_db():
response.raise_for_status() # Raise an exception for bad status codes response.raise_for_status() # Raise an exception for bad status codes
# --- VALIDATION --- # --- 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 # 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: if content_type not in expected_types:
logger.error(f"ERROR: Expected one of {expected_types} but got {content_type}.") logger.error(
logger.error("This usually indicates a server-side error or an incorrect master password.") 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) sys.exit(1)
# Check if the content is an HTML page (to handle incorrect passwords) # Check if the content is an HTML page (to handle incorrect passwords)
first_chunk = next(response.iter_content(chunk_size=128), b'') first_chunk = next(response.iter_content(chunk_size=128), b"")
if first_chunk.startswith(b'<'): if first_chunk.startswith(b"<"):
logger.error("ERROR: It seems the server returned an HTML page instead of a database file.") logger.error(
logger.error("This is often due to an incorrect master password or an invalid request.") "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("Server Response (First 200 chars):")
logger.error(response.text[:200]) logger.error(response.text[:200])
sys.exit(1) sys.exit(1)
@ -65,26 +81,35 @@ def download_odoo_db():
logger.info(f"Download started, saving to '{OUTPUT_FILE_NAME}'...") logger.info(f"Download started, saving to '{OUTPUT_FILE_NAME}'...")
output_path = Path(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 # Write the content from the first chunk to the file
f.write(first_chunk) f.write(first_chunk)
# Continue writing the rest of the stream in chunks # Continue writing the rest of the stream in chunks
for chunk in response.iter_content(chunk_size=8192): for chunk in response.iter_content(chunk_size=8192):
f.write(chunk) 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: 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: except Exception as e:
logger.error(f"An unexpected error occurred: {e}") logger.error(f"An unexpected error occurred: {e}")
# --- Script execution --- # --- Script execution ---
if __name__ == '__main__': if __name__ == "__main__":
# Add a simple check to ensure the user has configured the variables # Add a simple check to ensure the user has configured the variables
if ODOO_URL == 'http://localhost:8069' and DATABASE_NAME == 'your_database_name': if (
logger.error("Please configure the ODOO_URL, DATABASE_NAME, and MASTER_PASSWORD variables at the start of the script.") 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) sys.exit(1)
download_odoo_db() download_odoo_db()

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
from collections import defaultdict from collections import defaultdict

View file

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

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import requests import requests

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse
@ -7,7 +7,6 @@ import logging
import os import os
import sys import sys
new_path = os.path.normpath( new_path = os.path.normpath(
os.path.join(os.path.dirname(__file__), "..", "..") 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/CybroOdoo_OpenHRMS," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/ERPLibre_erplibre_addons," >> "${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_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-analytic," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_account-budgeting," >> "${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}" 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-invoicing," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_account-payment," >> "${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_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_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," >> "${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_bank-statement-import," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_brand," >> "${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}" 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-jira," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_connector-telephony," >> "${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_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_credit-control," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_crm," >> "${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_currency," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_data-protection," >> "${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}" 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_donation," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_e-commerce," >> "${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," >> "${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_event," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_field-service," >> "${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_fleet," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_geospatial," >> "${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_helpdesk," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_hr," >> "${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_hr-holidays," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_interface-github," >> "${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_knowledge," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_l10n-canada," >> "${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_maintenance," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_management-system," >> "${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_manufacture," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_margin-analysis," >> "${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," >> "${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_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_operating-unit," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_partner-contact," >> "${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_pos," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_product-attribute," >> "${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}" 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," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_project-agile," >> "${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_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_purchase-workflow," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_queue," >> "${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_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_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-reporting," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_sale-workflow," >> "${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-auth," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_server-backend," >> "${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-brand," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_server-env," >> "${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-tools," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_server-ux," >> "${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_sign," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_social," >> "${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_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-putaway," >> "${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-warehouse," >> "${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_storage," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_survey," >> "${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_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-association," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_vertical-hotel," >> "${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-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_vertical-travel," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_web," >> "${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," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OCA_website-cms," >> "${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/OCA_wms," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/OmniaGit_odooplm," >> "${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/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/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_odoo-modules," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/muk-it_muk_web," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/novacode-nl_odoo-formio," >> "${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/odoomates_odooapps," >> "${EL_CONFIG_FILE}"
printf "${EL_HOME_ODOO_PROJECT}/addons/openeducat_openeducat_erp," >> "${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 fi
printf "\n" >> "${EL_CONFIG_FILE}" printf "\n" >> "${EL_CONFIG_FILE}"

View file

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

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse 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( DEFAULT_PATH_MANIFEST_PRIVATE_CONF = os.path.join(
"private", "default_git_manifest.csv" "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(): def get_config():
@ -44,7 +46,11 @@ def get_config():
"--input", "--input",
help="First manifest to merge into input2. Second manifest, overwrite by input1.", 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( parser.add_argument(
"--att_revision_only", "--att_revision_only",
action="store_true", action="store_true",
@ -89,11 +95,14 @@ def main():
if os.path.exists(DEFAULT_PATH_INSTALLED_ODOO_VERSION): if os.path.exists(DEFAULT_PATH_INSTALLED_ODOO_VERSION):
with open(DEFAULT_PATH_INSTALLED_ODOO_VERSION, "r") as f: 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: if lst_installed_odoo_version:
for installed_odoo_version in lst_installed_odoo_version: for installed_odoo_version in lst_installed_odoo_version:
path_manifest_odoo_version = os.path.join( 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): if os.path.exists(path_manifest_odoo_version):
lst_input.append(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" f"ERROR: {path_manifest_odoo_version} does not exist"
) )
path_manifest_odoo_version = os.path.join( 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): if os.path.exists(path_manifest_odoo_version):
lst_input.append(path_manifest_odoo_version) lst_input.append(path_manifest_odoo_version)

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import os import os

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse
@ -26,6 +26,7 @@ _logger = logging.getLogger(__name__)
PROJECT_NAME = os.path.basename(os.getcwd()) PROJECT_NAME = os.path.basename(os.getcwd())
IDEA_PATH = "./.idea" IDEA_PATH = "./.idea"
DEFAULT_ODOO_BIN = "./odoo/odoo-bin" # Will be replaced dynamic
IDEA_MISC = os.path.join(IDEA_PATH, "misc.xml") IDEA_MISC = os.path.join(IDEA_PATH, "misc.xml")
IDEA_WORKSPACE = os.path.join(IDEA_PATH, "workspace.xml") IDEA_WORKSPACE = os.path.join(IDEA_PATH, "workspace.xml")
VCS_WORKSPACE = os.path.join(IDEA_PATH, "vcs.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 = ( PATH_DEFAULT_CONFIGURATION_PRIVATE = (
"./private/pycharm_default_configuration.private.csv" "./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(): def get_config():
@ -342,6 +349,10 @@ def add_configuration(dct_xml, file_name, config):
conf_default = bool(default_conf.get("default")) conf_default = bool(default_conf.get("default"))
if conf_default: if conf_default:
last_default = f"Python.{conf_name}" 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_replace = (
conf_script_path conf_script_path
if not conf_script_path.startswith("./") if not conf_script_path.startswith("./")

View file

@ -1,15 +1,15 @@
#!/usr/bin/env bash #!/usr/bin/env bash
install_package() { install_package() {
local package_name=$1 local package_name=$1
# Check package is already installed # Check package is already installed
if pacman -Qs "$package_name" > /dev/null; then if pacman -Qs "$package_name" >/dev/null; then
echo "$package_name is already installed." echo "$package_name is already installed."
else else
echo "Installation of package $package_name..." echo "Installation of package $package_name..."
yes|yay -S "$package_name" yes | yay -S "$package_name"
fi fi
} }
# Odoo installation # Odoo installation
@ -18,6 +18,7 @@ install_package postgresql
install_package mariadb install_package mariadb
install_package libev install_package libev
install_package wkhtmltopdf install_package wkhtmltopdf
install_package freetds
echo "Need password to create symbolic link, create postgres user and install npm :" echo "Need password to create symbolic link, create postgres user and install npm :"
sudo ln -fs /usr/lib/libldap.so /usr/lib/libldap_r.so sudo 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." echo "apt-get debian tool installation error."
exit 1 exit 1
fi fi
sudo apt-get install libmariadbd-dev -y sudo apt-get install libmariadbd-dev freetds-dev -y
retVal=$? retVal=$?
if [[ $retVal -ne 0 ]]; then if [[ $retVal -ne 0 ]]; then
echo "apt-get libmariadb installation error." echo "apt-get libmariadb installation error."

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import asyncio import asyncio

View file

@ -2,6 +2,7 @@
# © 2021-2025 TechnoLibre (http://www.technolibre.ca) # © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import os
import subprocess import subprocess
IGNORE_EXTENSION = [] IGNORE_EXTENSION = []
@ -15,51 +16,89 @@ def execute_shell(cmd):
def get_modified_files(): def get_modified_files():
lst_cmd_git_status = ["git", "status", "--porcelain"] 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: try:
print(" ".join(lst_cmd_git_status))
result = subprocess.run( result = subprocess.run(
lst_cmd_git_status, lst_cmd_git_status,
capture_output=True, capture_output=True,
text=True, text=True,
check=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 = [] modified_files = []
for line in lines: for directory, lines in lst_lines:
if not line: for line in lines:
continue if not line:
continue
try: try:
if "->" in line: has_space = False
# Example : M file_01 -> file_02 file_path_space = ""
status, old_file_path, code, file_path = ( if '"' in line:
line.strip().replace(" ", " ").split(" ") 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: else:
# Example : M file_01 print(f"Not supported status '{status}'")
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}'")
return modified_files return modified_files
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import json 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 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import datetime 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 import expected_conditions as EC
from selenium.webdriver.support.ui import Select, WebDriverWait 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 from script.config import config_file
logging.basicConfig( logging.basicConfig(
@ -253,9 +258,12 @@ class SeleniumLib(object):
firefox_options.set_preference("pdfjs.disabled", True) firefox_options.set_preference("pdfjs.disabled", True)
if self.config.window_size: if self.config.window_size:
# chrome_options.add_argument("--window-size=1920,1080") # chrome_options.add_argument("--window-size=1920,1080")
firefox_options.add_argument( # firefox_options.add_argument(
f"--window-size={self.config.window_size}" # 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: if self.config.headless:
firefox_options.add_argument("--headless") firefox_options.add_argument("--headless")

View file

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

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse
@ -97,7 +97,10 @@ def main():
# Default paths and fallback values (same logic as in the bash script) # Default paths and fallback values (same logic as in the bash script)
el_user = args.user el_user = args.user
el_home_erplibre = args.home_erplibre or os.getcwd() 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 = ( exec_param = (
" " " "
+ f" {w_cmd("-d", args.database or "")} {w_cmd("-p", args.port or "")}".strip() + f" {w_cmd("-d", args.database or "")} {w_cmd("-p", args.port or "")}".strip()

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse import argparse

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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) # 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 # This script need only basic importation, it needs to be supported by python of your system