From 7bfe6ac12f8d31b2064d0918be1ebf0c6698439b Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Sat, 12 Dec 2020 01:15:23 -0500 Subject: [PATCH 01/44] [FIX] doc docker --- doc/RELEASE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/RELEASE.md b/doc/RELEASE.md index 10fde8a..9fef491 100644 --- a/doc/RELEASE.md +++ b/doc/RELEASE.md @@ -80,7 +80,7 @@ When building your docker with script > ./script/docker_build.sh --release List your docker version -> docker image +> docker images You need to push your docker image and update your tag, like 1.0.1: > docker push technolibre/erplibre:VERSION From 206a9732a6f87a815e6f9c531b126640b3c240a0 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Tue, 2 Feb 2021 00:43:28 -0500 Subject: [PATCH 02/44] [FIX] makefile update manifest local dev code generator --- Makefile | 2 +- script/update_manifest_local_dev_code_generator.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index d240c9e..5584d70 100644 --- a/Makefile +++ b/Makefile @@ -251,7 +251,7 @@ config_gen_all: # generate config repo code_generator .PHONY: config_gen_code_generator config_gen_code_generator: - ./script/git_repo_update_group.py --group base,code_generator + ./script/git_repo_update_group.py --group base,code_generator ./script/install_locally.sh ################### diff --git a/script/update_manifest_local_dev_code_generator.sh b/script/update_manifest_local_dev_code_generator.sh index 8469bd0..907d45f 100755 --- a/script/update_manifest_local_dev_code_generator.sh +++ b/script/update_manifest_local_dev_code_generator.sh @@ -9,7 +9,7 @@ git daemon --base-path=. --export-all --reuseaddr --informative-errors --verbose & DAEMON_PID=$! -./.venv/repo init -u git://127.0.0.1:9418/ -b $(git rev-parse --verify HEAD) -m ${EL_MANIFEST_DEV} -g code_generator +./.venv/repo init -u git://127.0.0.1:9418/ -b $(git rev-parse --verify HEAD) -m ${EL_MANIFEST_DEV} -g base,code_generator ./.venv/repo sync -v --force-sync -m ${EL_MANIFEST_DEV} kill ${DAEMON_PID} From 7d8875139136c65b2fb4b45dc8eb9da050810728 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Tue, 2 Feb 2021 03:51:51 -0500 Subject: [PATCH 03/44] [ADD] makefile add template demo portal --- Makefile | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Makefile b/Makefile index 5584d70..49c6e92 100644 --- a/Makefile +++ b/Makefile @@ -121,6 +121,17 @@ addons_uninstall_code_generator_demo: .PHONY: addons_reinstall_code_generator_demo addons_reinstall_code_generator_demo: addons_uninstall_code_generator_demo addons_install_code_generator_demo +.PHONY: addons_install_code_generator_template_demo_portal +addons_install_code_generator_template_demo_portal: + ./run.sh --no-http --stop-after-init -d code_generator -i code_generator_template_demo_portal + +.PHONY: addons_uninstall_code_generator_template_demo_portal +addons_uninstall_code_generator_template_demo_portal: + ./run.sh --no-http --stop-after-init -d code_generator --uninstall code_generator_template_demo_portal + +.PHONY: addons_reinstall_code_generator_template_demo_portal +addons_reinstall_code_generator_template_demo_portal: addons_uninstall_code_generator_template_demo_portal addons_install_code_generator_template_demo_portal + .PHONY: addons_install_code_generator_demo_portal addons_install_code_generator_demo_portal: ./run.sh --no-http --stop-after-init -d code_generator -i code_generator_demo_portal -u code_generator_demo_portal From 60f78db43bc53b58ec74324ade405e3ede41ab20 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Tue, 2 Feb 2021 03:52:11 -0500 Subject: [PATCH 04/44] [FIX] script git change remote, ignore when repo not exist --- script/git_change_remote_https_to_git.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/script/git_change_remote_https_to_git.py b/script/git_change_remote_https_to_git.py index a77b50a..05cd37c 100755 --- a/script/git_change_remote_https_to_git.py +++ b/script/git_change_remote_https_to_git.py @@ -54,7 +54,12 @@ def main(): for repo in lst_repo: i += 1 print(f"Nb element {i}/{total}") - repo_sm = Repo(repo.get("name")) + repo_name = repo.get("name") + relative_path = os.path.join(new_path, repo_name) + if not os.path.isdir(relative_path): + print(f"Ignore repo {relative_path}") + continue + repo_sm = Repo(repo_name) if upstream_name: remote_upstream_name = [a for a in repo_sm.remotes if upstream_name == a.name] From aaaf41cbba5438fcfc1b7aebdfd747db43329185 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Tue, 2 Feb 2021 05:24:39 -0500 Subject: [PATCH 05/44] [ADD] makefile i18n demo_portal generation --- Makefile | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Makefile b/Makefile index 49c6e92..f597a5c 100644 --- a/Makefile +++ b/Makefile @@ -265,6 +265,15 @@ config_gen_code_generator: ./script/git_repo_update_group.py --group base,code_generator ./script/install_locally.sh +########## +# I18n # +########## + +# i18n generation demo_portal +.PHONY: i18n_generate_demo_portal +i18n_generate_demo_portal: + ./.venv/bin/python3 ./odoo/odoo-bin i18n --database code_generator --module demo_portal --addons_path addons/TechnoLibre_odoo-code-generator + ################### # Documentation # ################### From c17b89fb8fb6496a831ef174831d5b02fccf4845 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Sat, 6 Feb 2021 15:16:48 -0500 Subject: [PATCH 06/44] [ADD] manifest dev support erplibre_theme_addons to code_generator --- manifest/default.dev.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest/default.dev.xml b/manifest/default.dev.xml index a9b4c1d..77078c3 100644 --- a/manifest/default.dev.xml +++ b/manifest/default.dev.xml @@ -65,7 +65,7 @@ - + From 1e95b8b80f1b7219e679e8241c8a9a206c315ec6 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Sun, 7 Feb 2021 03:06:25 -0500 Subject: [PATCH 07/44] [ADD] makefile use install_addon.sh, reinstall_addon.sh, uninstall_addon.sh --- Makefile | 65 ++++++++++++++++++++++++++++++---------------- install_addon.sh | 2 ++ reinstall_addon.sh | 3 +++ uninstall_addon.sh | 2 ++ 4 files changed, 50 insertions(+), 22 deletions(-) create mode 100755 install_addon.sh create mode 100755 reinstall_addon.sh create mode 100755 uninstall_addon.sh diff --git a/Makefile b/Makefile index f597a5c..e46669b 100644 --- a/Makefile +++ b/Makefile @@ -92,19 +92,19 @@ db_drop_db_code_generator: ./.venv/bin/python3 ./odoo/odoo-bin db --drop --database code_generator .PHONY: db_restore_erplibre_base_db_test -db_restore_erplibre_base_db_test: +db_restore_erplibre_base_db_test: db_drop_db_test ./.venv/bin/python3 ./odoo/odoo-bin db --restore --restore_image erplibre_base --database test .PHONY: db_restore_erplibre_website_db_test -db_restore_erplibre_website_db_test: +db_restore_erplibre_website_db_test: db_drop_db_test ./.venv/bin/python3 ./odoo/odoo-bin db --restore --restore_image erplibre_website --database test .PHONY: db_restore_erplibre_website_chat_crm_db_test -db_restore_erplibre_website_chat_crm_db_test: +db_restore_erplibre_website_chat_crm_db_test: db_drop_db_test ./.venv/bin/python3 ./odoo/odoo-bin db --restore --restore_image erplibre_website_chat_crm --database test .PHONY: db_restore_erplibre_base_db_code_generator -db_restore_erplibre_base_db_code_generator: +db_restore_erplibre_base_db_code_generator: db_drop_db_code_generator ./.venv/bin/python3 ./odoo/odoo-bin db --restore --restore_image erplibre_base --database code_generator ######################### @@ -112,72 +112,93 @@ db_restore_erplibre_base_db_code_generator: ######################### .PHONY: addons_install_code_generator_demo addons_install_code_generator_demo: - ./run.sh --no-http --stop-after-init -d code_generator -i code_generator_demo -u code_generator_demo + ./install_addon.sh code_generator code_generator_demo .PHONY: addons_uninstall_code_generator_demo addons_uninstall_code_generator_demo: - ./run.sh --no-http --stop-after-init -d code_generator --uninstall code_generator_demo + ./uninstall_addon.sh code_generator code_generator_demo .PHONY: addons_reinstall_code_generator_demo addons_reinstall_code_generator_demo: addons_uninstall_code_generator_demo addons_install_code_generator_demo +.PHONY: addons_install_code_generator_demo_website_snippet +addons_install_code_generator_demo_website_snippet: + ./install_addon.sh code_generator code_generator_demo_website_snippet_content + ./install_addon.sh code_generator code_generator_demo_website_snippet_effect + ./install_addon.sh code_generator code_generator_demo_website_snippet_feature + ./install_addon.sh code_generator code_generator_demo_website_snippet_structure + +.PHONY: addons_uninstall_code_generator_demo_website_snippet +addons_uninstall_code_generator_demo_website_snippet: + ./uninstall_addon.sh code_generator code_generator_demo_website_snippet_content + ./uninstall_addon.sh code_generator code_generator_demo_website_snippet_effect + ./uninstall_addon.sh code_generator code_generator_demo_website_snippet_feature + ./uninstall_addon.sh code_generator code_generator_demo_website_snippet_structure + +.PHONY: addons_reinstall_code_generator_demo_website_snippet +addons_reinstall_code_generator_demo_website_snippet: addons_uninstall_code_generator_demo_website_snippet addons_install_code_generator_demo_website_snippet + .PHONY: addons_install_code_generator_template_demo_portal addons_install_code_generator_template_demo_portal: - ./run.sh --no-http --stop-after-init -d code_generator -i code_generator_template_demo_portal + ./install_addon.sh code_generator code_generator_template_demo_portal .PHONY: addons_uninstall_code_generator_template_demo_portal addons_uninstall_code_generator_template_demo_portal: - ./run.sh --no-http --stop-after-init -d code_generator --uninstall code_generator_template_demo_portal + ./uninstall_addon.sh code_generator code_generator_template_demo_portal .PHONY: addons_reinstall_code_generator_template_demo_portal addons_reinstall_code_generator_template_demo_portal: addons_uninstall_code_generator_template_demo_portal addons_install_code_generator_template_demo_portal .PHONY: addons_install_code_generator_demo_portal addons_install_code_generator_demo_portal: - ./run.sh --no-http --stop-after-init -d code_generator -i code_generator_demo_portal -u code_generator_demo_portal + ./install_addon.sh code_generator code_generator_demo_portal .PHONY: addons_uninstall_code_generator_demo_portal addons_uninstall_code_generator_demo_portal: - ./run.sh --no-http --stop-after-init -d code_generator --uninstall code_generator_demo_portal - ./run.sh --no-http --stop-after-init -d code_generator --uninstall code_generator_demo + ./uninstall_addon.sh code_generator code_generator_demo_portal + ./uninstall_addon.sh code_generator code_generator_demo .PHONY: addons_reinstall_code_generator_demo_portal addons_reinstall_code_generator_demo_portal: addons_uninstall_code_generator_demo_portal addons_install_code_generator_demo_portal .PHONY: addons_install_demo_portal_on_code_generator addons_install_demo_portal_on_code_generator: - ./run.sh --no-http --stop-after-init -d code_generator -i demo_portal -u demo_portal + ./install_addon.sh code_generator demo_portal .PHONY: addons_uninstall_demo_portal_on_code_generator addons_uninstall_demo_portal_on_code_generator: - ./run.sh --no-http --stop-after-init -d code_generator --uninstall demo_portal + ./uninstall_addon.sh code_generator demo_portal .PHONY: addons_reinstall_demo_portal_on_code_generator addons_reinstall_demo_portal_on_code_generator: addons_uninstall_demo_portal_on_code_generator addons_install_demo_portal_on_code_generator .PHONY: addons_install_demo_portal_on_test addons_install_demo_portal_on_test: - ./run.sh --no-http --stop-after-init -d test -i demo_portal -u demo_portal + ./install_addon.sh test demo_portal .PHONY: addons_uninstall_demo_portal_on_test addons_uninstall_demo_portal_on_test: - ./run.sh --no-http --stop-after-init -d test --uninstall demo_portal + ./uninstall_addon.sh test demo_portal .PHONY: addons_reinstall_demo_portal_on_test addons_reinstall_demo_portal_on_test: addons_uninstall_demo_portal_on_test addons_install_demo_portal_on_test +.PHONY: addons_install_demo_website_snippet_on_test +addons_install_demo_website_snippet_on_test: + ./install_addon.sh test demo_website_snippet_content,demo_website_snippet_effect,demo_website_snippet_feature,demo_website_snippet_structure + .PHONY: addons_install_all_code_generator_demo addons_install_all_code_generator_demo: - ./run.sh --no-http --stop-after-init -d code_generator -i code_generator_demo -u code_generator_demo - ./run.sh --no-http --stop-after-init -d code_generator -i code_generator_demo_export_helpdesk -u code_generator_demo_export_helpdesk - ./run.sh --no-http --stop-after-init -d code_generator -i code_generator_demo_internal -u code_generator_demo_internal - ./run.sh --no-http --stop-after-init -d code_generator -i code_generator_demo_portal -u code_generator_demo_portal - ./run.sh --no-http --stop-after-init -d code_generator -i code_generator_demo_theme_website -u code_generator_demo_theme_website - ./run.sh --no-http --stop-after-init -d code_generator -i code_generator_demo_website_leaflet -u code_generator_demo_website_leaflet + ./install_addon.sh code_generator code_generator_demo + ./install_addon.sh code_generator code_generator_demo_export_helpdesk + ./install_addon.sh code_generator code_generator_demo_internal + ./install_addon.sh code_generator code_generator_demo_portal + ./install_addon.sh code_generator code_generator_demo_theme_website + ./install_addon.sh code_generator code_generator_demo_website_leaflet .PHONY: addons_uninstall_all_code_generator_demo addons_uninstall_all_code_generator_demo: - ./run.sh --no-http --stop-after-init -d code_generator --uninstall code_generator_demo,code_generator_demo_export_helpdesk,code_generator_demo_internal,code_generator_demo_portal,code_generator_demo_theme_website,code_generator_demo_website_leaflet + ./uninstall_addon.sh code_generator code_generator_demo,code_generator_demo_export_helpdesk,code_generator_demo_internal,code_generator_demo_portal,code_generator_demo_theme_website,code_generator_demo_website_leaflet ############ # docker # diff --git a/install_addon.sh b/install_addon.sh new file mode 100755 index 0000000..f29739d --- /dev/null +++ b/install_addon.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +./run.sh --no-http --stop-after-init -d $1 -i $2 -u $2 diff --git a/reinstall_addon.sh b/reinstall_addon.sh new file mode 100755 index 0000000..8e420d4 --- /dev/null +++ b/reinstall_addon.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +./uninstall_addon.sh $1 $2 +./install_addon.sh $1 $2 diff --git a/uninstall_addon.sh b/uninstall_addon.sh new file mode 100755 index 0000000..65c3ce9 --- /dev/null +++ b/uninstall_addon.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +./run.sh --no-http --stop-after-init -d $1 --uninstall $2 From e5eb68f3e31c053e88de5f52c7d17a53f378fb37 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Wed, 10 Feb 2021 22:15:07 -0500 Subject: [PATCH 08/44] [ADD] doc code generator - Explication about general usage of code generator - How to generate i18n translation - How to synchronize code_generator with module --- doc/CODE_GENERATOR.md | 123 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 doc/CODE_GENERATOR.md diff --git a/doc/CODE_GENERATOR.md b/doc/CODE_GENERATOR.md new file mode 100644 index 0000000..d31d832 --- /dev/null +++ b/doc/CODE_GENERATOR.md @@ -0,0 +1,123 @@ +# How to generate code + +Never run this on production environment, this create circular dependencies and will cause frustration to clean damage. + +``` +Modules +############ ################## ########## +# Template # -> # Code_Generator # -> # Module # +############ ################## ########## +``` +1. [A Template generates a Template or a Code_Generator.](Create your first code generator) +2. A Code_Generator generates a Module. +3. A Template reads a Module to generate a Code_Generator. + +## Prepare a DB + +This will destroy and create database named code_generator. +```bash +make db_restore_erplibre_base_db_code_generator +``` + +## Create your first Code_Generator + +Edit [Code Generator Demo](./../addons/TechnoLibre_odoo-code-generator/code_generator_demo/hooks.py) and update `# TODO HUMAN:` + +### Generate a Template + +By default, code_generator_demo generate itself, code_generator_demo. + +Name your module begin with `MODULE_NAME = "code_generator_template_"` + +The value "enable_template_code_generator_demo" at False to create a new template module, else this will recreate code_generator_demo. + +```python +value["enable_template_code_generator_demo"] = True +``` + +Example, to generate the module `code_generator_template_demo_website_snippet`, change value +```python +MODULE_NAME = "code_generator_template_demo_website_snippet" +[...] +value["enable_template_website_snippet_view"] = True +[...] +lst_depend = [ + "code_generator", + "code_generator_website_snippet", +] +``` +Generate new module, this will overwrite code_generator_template_demo_website_snippet: +```bash +make addons_install_code_generator_demo +``` + +### Generate a Code_Generator + +Name your module begin with `MODULE_NAME = "code_generator_demo_"` + +Disable enable_template_code_generator_demo +```python +value["enable_template_code_generator_demo"] = False +``` + +Continue the example, you generated the template `code_generator_template_demo_website_snippet`, this will overwrite code_generator_demo_website_snippet: +```bash +./install_addon.sh code_generator code_generator_template_demo_website_snippet +``` + +## Create your first Module + +Continue example of code_generator_demo_website_snippet to generate your first module. Update next value: +```python +"application": True, +"category_id": env.ref("base.module_category_website").id, +[...] +# Add dependencies +lst_depend = [ + "website", +] +``` + +Generate your module: +```bash +./install_addon.sh code_generator code_generator_demo_website_snippet +``` + +Now, you can test it! Note, you cannot install a generated module with is code_generator associated, because duplicated models! +Generate your module: +```bash +# Optional, reset test database +make db_restore_erplibre_base_db_test +./install_addon.sh test demo_website_snippet +``` + +# How to generate i18n translation + +You need a template and a module. +Be sure you have this line in template: + +```python +new_module_path = os.path.join(path_module_generate, new_module_name) +code_generator_writer.set_module_translator(new_module_name, new_module_path) +``` + +First, install the module, example demo_portal, and after the template, example code_generator_template_demo_portal +```bash +make db_restore_erplibre_base_db_code_generator +./install_addon.sh test demo_portal +./install_addon.sh test code_generator_template_demo_portal +``` + +# Sync Code_Generator fields from Module + +This reduce time of programming a Code_Generator with sync module field with Template. + +You need a Template, a Code_Generator with his Module. Install the Module first in clean database and install Template, this will generate the Code_generator, use `enable_sync_template` at True. + +Example +```bash +make db_restore_erplibre_base_db_code_generator +./install_addon.sh test demo_portal +./install_addon.sh test code_generator_template_demo_portal +``` + From d7aa5261991bd9af9164fd997887b8036a7e2cc9 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Sat, 6 Mar 2021 23:04:26 -0500 Subject: [PATCH 09/44] [ADD] Update odoo-development documentation --- manifest/default.dev.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest/default.dev.xml b/manifest/default.dev.xml index 77078c3..9692be5 100644 --- a/manifest/default.dev.xml +++ b/manifest/default.dev.xml @@ -93,7 +93,7 @@ - + From 67a21ce1a5e77b241ed45b96f01eddf68894d141 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Sat, 6 Mar 2021 23:36:39 -0500 Subject: [PATCH 10/44] [ADD] update manifest dev muk_web to 12.0_dev --- manifest/default.dev.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest/default.dev.xml b/manifest/default.dev.xml index 9692be5..bfc50af 100644 --- a/manifest/default.dev.xml +++ b/manifest/default.dev.xml @@ -86,7 +86,7 @@ - + From 46c4072d7ca657d4aeb835c8acaa034bc9d8d444 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Tue, 9 Mar 2021 04:28:31 -0500 Subject: [PATCH 11/44] [ADD] contract signature feature --- manifest/default.dev.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest/default.dev.xml b/manifest/default.dev.xml index bfc50af..a819353 100644 --- a/manifest/default.dev.xml +++ b/manifest/default.dev.xml @@ -51,7 +51,7 @@ - + From ae0242e32d810bf0743ecb7682cd32c24ad59041 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Sat, 13 Mar 2021 02:21:45 -0500 Subject: [PATCH 12/44] [ADD] makefile repo_configure_all --- Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Makefile b/Makefile index e46669b..f4b4a4e 100644 --- a/Makefile +++ b/Makefile @@ -251,6 +251,11 @@ docker_clean_all: repo_clear_all: ./script/clean_repo_manifest.sh +# configure all repo +.PHONY: repo_configure_all +repo_configure_all: + ./script/update_manifest_local_dev.sh + # configure only group code_generator .PHONY: repo_configure_group_code_generator repo_configure_group_code_generator: From 724569c9809cb6de6190ea3b6ca98f209bf149ee Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Sat, 13 Mar 2021 02:27:33 -0500 Subject: [PATCH 13/44] [ADD] TechnoLibre_odoo-code-generator-template --- manifest/default.dev.xml | 1 + script/install_locally.sh | 1 + source_repo_addons.csv | 1 + 3 files changed, 3 insertions(+) diff --git a/manifest/default.dev.xml b/manifest/default.dev.xml index a819353..19219ae 100644 --- a/manifest/default.dev.xml +++ b/manifest/default.dev.xml @@ -92,6 +92,7 @@ + diff --git a/script/install_locally.sh b/script/install_locally.sh index 9a5387b..6bcd621 100755 --- a/script/install_locally.sh +++ b/script/install_locally.sh @@ -129,6 +129,7 @@ if [[ ${EL_MINIMAL_ADDONS} = "False" ]]; then printf "${EL_HOME}/addons/OCA_wms," >> ${EL_CONFIG_FILE} printf "${EL_HOME}/addons/Smile-SA_odoo_addons," >> ${EL_CONFIG_FILE} printf "${EL_HOME}/addons/TechnoLibre_odoo-code-generator," >> ${EL_CONFIG_FILE} + printf "${EL_HOME}/addons/TechnoLibre_odoo-code-generator-template," >> ${EL_CONFIG_FILE} printf "${EL_HOME}/addons/camptocamp_odoo-cloud-platform," >> ${EL_CONFIG_FILE} printf "${EL_HOME}/addons/dhongu_deltatech," >> ${EL_CONFIG_FILE} printf "${EL_HOME}/addons/it-projects-llc_odoo-saas-tools," >> ${EL_CONFIG_FILE} diff --git a/source_repo_addons.csv b/source_repo_addons.csv index efa6147..b9da87a 100644 --- a/source_repo_addons.csv +++ b/source_repo_addons.csv @@ -126,3 +126,4 @@ https://github.com/itpp-labs/odoo-test-docs.git,doc,master, https://github.com/odoo/documentation-user.git,doc,, https://github.com/OCA/odoo-module-migrator.git,script,master, https://github.com/TechnoLibre/odoo-code-generator.git,addons,, +https://github.com/TechnoLibre/odoo-code-generator-template.git,addons,, From 7e4972355da38d40139f6c532844dbe96ab2b243 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Sat, 13 Mar 2021 02:41:19 -0500 Subject: [PATCH 14/44] [FIX] missing ERPLibre_image_db in source_repo_addons - Remove it from config, no need for now --- script/git_tool.py | 4 ++-- script/install_locally.sh | 1 - source_repo_addons.csv | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/script/git_tool.py b/script/git_tool.py index 327d865..f91cb8b 100644 --- a/script/git_tool.py +++ b/script/git_tool.py @@ -370,8 +370,8 @@ class GitTool: lst_result = [] for repo in lst_repo: # Exception, ignore addons/OCA_web and root - if "addons/OCA_web" == repo.get("path") or \ - "odoo" == repo.get("path"): + if "addons/OCA_web" == repo.get("path") or "odoo" == repo.get("path") or \ + "ERPLibre_image_db" == repo.get("path"): continue str_repo = f' printf "${{EL_HOME}}/{repo.get("path")}," >> ' \ f'${{EL_CONFIG_FILE}}\n' diff --git a/script/install_locally.sh b/script/install_locally.sh index 6bcd621..362f5e9 100755 --- a/script/install_locally.sh +++ b/script/install_locally.sh @@ -155,7 +155,6 @@ if [[ ${EL_MINIMAL_ADDONS} = "False" ]]; then printf "${EL_HOME}/doc/itpp-labs_odoo-port-docs," >> ${EL_CONFIG_FILE} printf "${EL_HOME}/doc/itpp-labs_odoo-test-docs," >> ${EL_CONFIG_FILE} printf "${EL_HOME}/doc/odoo_documentation-user," >> ${EL_CONFIG_FILE} - printf "${EL_HOME}/image_db," >> ${EL_CONFIG_FILE} printf "${EL_HOME}/script/OCA_odoo-module-migrator," >> ${EL_CONFIG_FILE} fi printf "\n" >> ${EL_CONFIG_FILE} diff --git a/source_repo_addons.csv b/source_repo_addons.csv index b9da87a..1447f16 100644 --- a/source_repo_addons.csv +++ b/source_repo_addons.csv @@ -127,3 +127,4 @@ https://github.com/odoo/documentation-user.git,doc,, https://github.com/OCA/odoo-module-migrator.git,script,master, https://github.com/TechnoLibre/odoo-code-generator.git,addons,, https://github.com/TechnoLibre/odoo-code-generator-template.git,addons,, +https://github.com/ERPLibre/ERPLibre_image_db.git,,, From 48fce9e1f03b02b08482e8a5b6abb975d3cd9b93 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Mon, 15 Mar 2021 02:54:48 -0400 Subject: [PATCH 15/44] [ADD] db_restore and update makefile, clean unsued install addons - db_restore create a _cache_DB and clone for each restore call - This increase speed, 18s to 3s execution - Makefile: add test2 and test3 add erplibre_ecommerce_base --- Makefile | 110 ++++++++++++++----------------------------- script/db_restore.py | 83 ++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 74 deletions(-) create mode 100755 script/db_restore.py diff --git a/Makefile b/Makefile index f4b4a4e..c479603 100644 --- a/Makefile +++ b/Makefile @@ -87,25 +87,53 @@ db_version: db_drop_db_test: ./.venv/bin/python3 ./odoo/odoo-bin db --drop --database test +.PHONY: db_drop_db_test2 +db_drop_db_test2: + ./.venv/bin/python3 ./odoo/odoo-bin db --drop --database test2 + +.PHONY: db_drop_db_test3 +db_drop_db_test3: + ./.venv/bin/python3 ./odoo/odoo-bin db --drop --database test3 + .PHONY: db_drop_db_code_generator db_drop_db_code_generator: ./.venv/bin/python3 ./odoo/odoo-bin db --drop --database code_generator +.PHONY: db_drop_db_template +db_drop_db_template: + ./.venv/bin/python3 ./odoo/odoo-bin db --drop --database template + .PHONY: db_restore_erplibre_base_db_test -db_restore_erplibre_base_db_test: db_drop_db_test - ./.venv/bin/python3 ./odoo/odoo-bin db --restore --restore_image erplibre_base --database test +db_restore_erplibre_base_db_test: + ./script/db_restore.py --database test + +.PHONY: db_restore_erplibre_base_db_test2 +db_restore_erplibre_base_db_test2: + ./script/db_restore.py --database test2 + +.PHONY: db_restore_erplibre_base_db_test3 +db_restore_erplibre_base_db_test3: + ./script/db_restore.py --database test3 .PHONY: db_restore_erplibre_website_db_test -db_restore_erplibre_website_db_test: db_drop_db_test - ./.venv/bin/python3 ./odoo/odoo-bin db --restore --restore_image erplibre_website --database test +db_restore_erplibre_website_db_test: + ./script/db_restore.py --database test --image erplibre_website .PHONY: db_restore_erplibre_website_chat_crm_db_test -db_restore_erplibre_website_chat_crm_db_test: db_drop_db_test - ./.venv/bin/python3 ./odoo/odoo-bin db --restore --restore_image erplibre_website_chat_crm --database test +db_restore_erplibre_website_chat_crm_db_test: + ./script/db_restore.py --database test --image erplibre_website_chat_crm + +.PHONY: db_restore_erplibre_ecommerce_base_db_test +db_restore_erplibre_ecommerce_base_db_test: + ./script/db_restore.py --database test --image erplibre_ecommerce_base .PHONY: db_restore_erplibre_base_db_code_generator -db_restore_erplibre_base_db_code_generator: db_drop_db_code_generator - ./.venv/bin/python3 ./odoo/odoo-bin db --restore --restore_image erplibre_base --database code_generator +db_restore_erplibre_base_db_code_generator: + ./script/db_restore.py --database code_generator + +.PHONY: db_restore_erplibre_base_db_template +db_restore_erplibre_base_db_template: + ./script/db_restore.py --database template ######################### # Addons installation # @@ -121,72 +149,6 @@ addons_uninstall_code_generator_demo: .PHONY: addons_reinstall_code_generator_demo addons_reinstall_code_generator_demo: addons_uninstall_code_generator_demo addons_install_code_generator_demo -.PHONY: addons_install_code_generator_demo_website_snippet -addons_install_code_generator_demo_website_snippet: - ./install_addon.sh code_generator code_generator_demo_website_snippet_content - ./install_addon.sh code_generator code_generator_demo_website_snippet_effect - ./install_addon.sh code_generator code_generator_demo_website_snippet_feature - ./install_addon.sh code_generator code_generator_demo_website_snippet_structure - -.PHONY: addons_uninstall_code_generator_demo_website_snippet -addons_uninstall_code_generator_demo_website_snippet: - ./uninstall_addon.sh code_generator code_generator_demo_website_snippet_content - ./uninstall_addon.sh code_generator code_generator_demo_website_snippet_effect - ./uninstall_addon.sh code_generator code_generator_demo_website_snippet_feature - ./uninstall_addon.sh code_generator code_generator_demo_website_snippet_structure - -.PHONY: addons_reinstall_code_generator_demo_website_snippet -addons_reinstall_code_generator_demo_website_snippet: addons_uninstall_code_generator_demo_website_snippet addons_install_code_generator_demo_website_snippet - -.PHONY: addons_install_code_generator_template_demo_portal -addons_install_code_generator_template_demo_portal: - ./install_addon.sh code_generator code_generator_template_demo_portal - -.PHONY: addons_uninstall_code_generator_template_demo_portal -addons_uninstall_code_generator_template_demo_portal: - ./uninstall_addon.sh code_generator code_generator_template_demo_portal - -.PHONY: addons_reinstall_code_generator_template_demo_portal -addons_reinstall_code_generator_template_demo_portal: addons_uninstall_code_generator_template_demo_portal addons_install_code_generator_template_demo_portal - -.PHONY: addons_install_code_generator_demo_portal -addons_install_code_generator_demo_portal: - ./install_addon.sh code_generator code_generator_demo_portal - -.PHONY: addons_uninstall_code_generator_demo_portal -addons_uninstall_code_generator_demo_portal: - ./uninstall_addon.sh code_generator code_generator_demo_portal - ./uninstall_addon.sh code_generator code_generator_demo - -.PHONY: addons_reinstall_code_generator_demo_portal -addons_reinstall_code_generator_demo_portal: addons_uninstall_code_generator_demo_portal addons_install_code_generator_demo_portal - -.PHONY: addons_install_demo_portal_on_code_generator -addons_install_demo_portal_on_code_generator: - ./install_addon.sh code_generator demo_portal - -.PHONY: addons_uninstall_demo_portal_on_code_generator -addons_uninstall_demo_portal_on_code_generator: - ./uninstall_addon.sh code_generator demo_portal - -.PHONY: addons_reinstall_demo_portal_on_code_generator -addons_reinstall_demo_portal_on_code_generator: addons_uninstall_demo_portal_on_code_generator addons_install_demo_portal_on_code_generator - -.PHONY: addons_install_demo_portal_on_test -addons_install_demo_portal_on_test: - ./install_addon.sh test demo_portal - -.PHONY: addons_uninstall_demo_portal_on_test -addons_uninstall_demo_portal_on_test: - ./uninstall_addon.sh test demo_portal - -.PHONY: addons_reinstall_demo_portal_on_test -addons_reinstall_demo_portal_on_test: addons_uninstall_demo_portal_on_test addons_install_demo_portal_on_test - -.PHONY: addons_install_demo_website_snippet_on_test -addons_install_demo_website_snippet_on_test: - ./install_addon.sh test demo_website_snippet_content,demo_website_snippet_effect,demo_website_snippet_feature,demo_website_snippet_structure - .PHONY: addons_install_all_code_generator_demo addons_install_all_code_generator_demo: ./install_addon.sh code_generator code_generator_demo diff --git a/script/db_restore.py b/script/db_restore.py new file mode 100755 index 0000000..67e69ce --- /dev/null +++ b/script/db_restore.py @@ -0,0 +1,83 @@ +#!./.venv/bin/python +import os +import sys +import argparse +import logging +from subprocess import check_output + +new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '..')) +sys.path.append(new_path) + +logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO")) + +_logger = logging.getLogger(__name__) + + +def get_config(): + """Parse command line arguments, extracting the config file name, + returning the union of config file and command line arguments + + :return: dict of config file settings and command line arguments + """ + # TODO update description + parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description='''\ + Restore database, use cache to clone to improve speed. +''', + epilog='''\ +''' + ) + # parser.add_argument('-d', '--dir', dest="dir", default="./", + # help="Path of repo to change remote, including submodule.") + parser.add_argument('--database', help="Database to manipulate.") + parser.add_argument('--image', default="erplibre_base", + help="Image name to restore, from directory image_db, filename without '.zip'. " + "Example, use erplibre_base to use image erplibre_base.zip.") + parser.add_argument('--clean_cache', action="store_true", help="Delete all database cache to clone, " + "begin by _cache_.") + args = parser.parse_args() + return args + + +def main(): + config = get_config() + + # Get list of database + arg = "./.venv/bin/python3 ./odoo/odoo-bin db --list" + out = check_output(arg.split(" ")).decode() + lst_db = out.strip().split("\n") + lst_db_cache = [a for a in lst_db if a.startswith("_cache_")] + + if config.clean_cache: + for db in lst_db_cache: + _logger.info(f"## Delete {db} ##") + arg = f"./.venv/bin/python3 ./odoo/odoo-bin db --drop --database {db}" + out = check_output(arg.split(" ")).decode() + print(out) + + if config.database: + cache_database = f"_cache_{config.image}" + # Drop db + if config.database in lst_db: + _logger.info(f"## Drop {config.database} ##") + arg = f"./.venv/bin/python3 ./odoo/odoo-bin db --drop --database {config.database}" + out = check_output(arg.split(" ")).decode() + print(out) + # Check cache exist + if cache_database not in lst_db_cache: + _logger.info(f"## Create cache {cache_database} from image {config.image} ##") + arg = f"./.venv/bin/python3 ./odoo/odoo-bin db --restore --restore_image {config.image} " \ + f"--database {cache_database}" + out = check_output(arg.split(" ")).decode() + print(out) + # Clone database + _logger.info(f"## Clone cache {cache_database} to database {config.database} ##") + arg = f"./.venv/bin/python3 ./odoo/odoo-bin db --clone --from_database {cache_database} " \ + f"--database {config.database}" + out = check_output(arg.split(" ")).decode() + print(out) + + +if __name__ == '__main__': + main() From cc5a864c0146835fb7154797697700e505a11e82 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Mon, 15 Mar 2021 06:46:13 -0400 Subject: [PATCH 16/44] [ADD] Makefile: time to db_restore --- Makefile | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index c479603..a1633ae 100644 --- a/Makefile +++ b/Makefile @@ -97,43 +97,43 @@ db_drop_db_test3: .PHONY: db_drop_db_code_generator db_drop_db_code_generator: - ./.venv/bin/python3 ./odoo/odoo-bin db --drop --database code_generator + time ./.venv/bin/python3 ./odoo/odoo-bin db --drop --database code_generator .PHONY: db_drop_db_template db_drop_db_template: - ./.venv/bin/python3 ./odoo/odoo-bin db --drop --database template + time ./.venv/bin/python3 ./odoo/odoo-bin db --drop --database template .PHONY: db_restore_erplibre_base_db_test db_restore_erplibre_base_db_test: - ./script/db_restore.py --database test + time ./script/db_restore.py --database test .PHONY: db_restore_erplibre_base_db_test2 db_restore_erplibre_base_db_test2: - ./script/db_restore.py --database test2 + time ./script/db_restore.py --database test2 .PHONY: db_restore_erplibre_base_db_test3 db_restore_erplibre_base_db_test3: - ./script/db_restore.py --database test3 + time ./script/db_restore.py --database test3 .PHONY: db_restore_erplibre_website_db_test db_restore_erplibre_website_db_test: - ./script/db_restore.py --database test --image erplibre_website + time ./script/db_restore.py --database test --image erplibre_website .PHONY: db_restore_erplibre_website_chat_crm_db_test db_restore_erplibre_website_chat_crm_db_test: - ./script/db_restore.py --database test --image erplibre_website_chat_crm + time ./script/db_restore.py --database test --image erplibre_website_chat_crm .PHONY: db_restore_erplibre_ecommerce_base_db_test db_restore_erplibre_ecommerce_base_db_test: - ./script/db_restore.py --database test --image erplibre_ecommerce_base + time ./script/db_restore.py --database test --image erplibre_ecommerce_base .PHONY: db_restore_erplibre_base_db_code_generator db_restore_erplibre_base_db_code_generator: - ./script/db_restore.py --database code_generator + time ./script/db_restore.py --database code_generator .PHONY: db_restore_erplibre_base_db_template db_restore_erplibre_base_db_template: - ./script/db_restore.py --database template + time ./script/db_restore.py --database template ######################### # Addons installation # From 558978722930344c776eb16b7851212e19592e0e Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Tue, 16 Mar 2021 18:59:20 -0400 Subject: [PATCH 17/44] [ADD] Makefile generate all code_generator and add test --- Makefile | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index a1633ae..5ea103c 100644 --- a/Makefile +++ b/Makefile @@ -157,10 +157,35 @@ addons_install_all_code_generator_demo: ./install_addon.sh code_generator code_generator_demo_portal ./install_addon.sh code_generator code_generator_demo_theme_website ./install_addon.sh code_generator code_generator_demo_website_leaflet + ./install_addon.sh code_generator code_generator_demo_website_snippet -.PHONY: addons_uninstall_all_code_generator_demo -addons_uninstall_all_code_generator_demo: - ./uninstall_addon.sh code_generator code_generator_demo,code_generator_demo_export_helpdesk,code_generator_demo_internal,code_generator_demo_portal,code_generator_demo_theme_website,code_generator_demo_website_leaflet +.PHONY: addons_install_all_code_generator_template +addons_install_all_code_generator_template: + ./install_addon.sh template demo_portal,auto_backup + ./install_addon.sh template code_generator_template_demo_portal + ./install_addon.sh template code_generator_template_demo_sysadmin_cron + +.PHONY: addons_install_all_generated_demo +addons_install_all_generated_demo: + ./install_addon.sh template demo_export_helpdesk,demo_internal,demo_portal,demo_website_leaflet,demo_website_snippet + # TODO support installation theme with cli + #./install_addon.sh template theme_website_demo_code_generator + +.PHONY: addons_install_all_code_generator +addons_install_all_code_generator: + ./install_addon.sh code_generator code_generator_auto_backup + +########## +# test # +########## +.PHONY: test_code_generator_generation +test_code_generator_generation: db_restore_erplibre_base_db_code_generator addons_install_all_code_generator_demo + +.PHONY: test_code_generator_template +test_code_generator_template: db_restore_erplibre_base_db_template addons_install_all_code_generator_template + +.PHONY: test_code_generator_demo +test_code_generator_demo: db_restore_erplibre_base_db_template addons_install_all_generated_demo ############ # docker # From 99662ab8ddaff6cac67ace6d18a600c024ead02d Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Tue, 16 Mar 2021 23:13:41 -0400 Subject: [PATCH 18/44] [ADD] repo_revert_git_diff_date_from_code_generator - This script revert line when a diff is a changing date - The code generator always change date for no important reason --- Makefile | 18 +++- install_addon.sh | 1 + requirements.txt | 1 + ...evert_git_diff_date_from_code_generator.py | 87 +++++++++++++++++++ 4 files changed, 104 insertions(+), 3 deletions(-) create mode 100755 script/repo_revert_git_diff_date_from_code_generator.py diff --git a/Makefile b/Makefile index 5ea103c..63cad86 100644 --- a/Makefile +++ b/Makefile @@ -179,13 +179,25 @@ addons_install_all_code_generator: # test # ########## .PHONY: test_code_generator_generation -test_code_generator_generation: db_restore_erplibre_base_db_code_generator addons_install_all_code_generator_demo +test_code_generator_generation: db_restore_erplibre_base_db_code_generator addons_install_all_code_generator_demo clean_code_generator_template .PHONY: test_code_generator_template -test_code_generator_template: db_restore_erplibre_base_db_template addons_install_all_code_generator_template +test_code_generator_template: db_restore_erplibre_base_db_template addons_install_all_code_generator_template clean_code_generator_template .PHONY: test_code_generator_demo -test_code_generator_demo: db_restore_erplibre_base_db_template addons_install_all_generated_demo +test_code_generator_demo: db_restore_erplibre_base_db_template addons_install_all_generated_demo clean_code_generator_template + +.PHONY: test_code_generator_demo_portal +test_code_generator_demo_portal: db_restore_erplibre_base_db_code_generator + ./install_addon.sh code_generator code_generator_demo_portal + ./script/repo_revert_git_diff_date_from_code_generator.py + +########### +# clean # +########### +.PHONY: clean_code_generator_template +clean_code_generator_template: + ./script/repo_revert_git_diff_date_from_code_generator.py ############ # docker # diff --git a/install_addon.sh b/install_addon.sh index f29739d..697e520 100755 --- a/install_addon.sh +++ b/install_addon.sh @@ -1,2 +1,3 @@ #!/usr/bin/env bash ./run.sh --no-http --stop-after-init -d $1 -i $2 -u $2 +echo "" diff --git a/requirements.txt b/requirements.txt index 6f619c9..e4bb4da 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,6 +6,7 @@ PyYAML retrying xmltodict openupgradelib +unidiff # For OSX cython diff --git a/script/repo_revert_git_diff_date_from_code_generator.py b/script/repo_revert_git_diff_date_from_code_generator.py new file mode 100755 index 0000000..7a9793e --- /dev/null +++ b/script/repo_revert_git_diff_date_from_code_generator.py @@ -0,0 +1,87 @@ +#!./.venv/bin/python +import os +import sys +import argparse +import logging +import git +from unidiff import PatchSet +import re + +new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '..')) +sys.path.append(new_path) + +_logger = logging.getLogger(__name__) + + +def get_config(): + """Parse command line arguments, extracting the config file name, + returning the union of config file and command line arguments + + :return: dict of config file settings and command line arguments + """ + # TODO update description + parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description='''\ +''', + epilog='''\ +''' + ) + args = parser.parse_args() + return args + + +def main(): + config = get_config() + # rex = r"\s+(?=\d{2}(?:\d{2})?-\d{1,2}-\d{1,2}\b)" + rex = r"[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) (2[0-3]|[01][0-9]):[0-5][0-9]" + path = "./addons/TechnoLibre_odoo-code-generator-template" + repo = git.Repo(path) + supported_ext = [".xml", ".pot", ".po"] + for diff in repo.index.diff(None, create_patch=True): + # if diff.change_type == "M": + file_path = diff.a_path + filename, file_extension = os.path.splitext(file_path) + if file_extension in supported_ext: + file_real_path = os.path.join(path, diff.a_path) + if not os.path.isfile(file_real_path): + continue + str_diff = repo.git.diff(diff.a_path) + patch = PatchSet(str_diff) + for modified_file in patch.modified_files: + lst_to_write = [] + for hunk in modified_file: + nb_line_source = len(hunk.source) + nb_line_target = len(hunk.target) + if nb_line_source != nb_line_target: + # TODO support different line + continue + # try: + # assert nb_line_source == nb_line_target, f"Not the same line of diff:\n{str_diff}" + # except Exception as e: + # print(e) + for i in range(nb_line_source): + result_source = re.split(rex, hunk.source[i]) + if i > len(hunk.target): + result_target = re.split(rex, hunk.target[i]) + else: + result_target = "" + if len(result_source) > 1 or len(result_target) > 1: + line_to_change = hunk.target_start + i - 1 + lst_to_write.append((line_to_change, hunk.source[i][1:])) + # rewrite + rewrite(file_real_path, lst_to_write) + + +def rewrite(file_path, lst_to_write): + # TODO not optimal for big file + with open(file_path, 'r') as file: + data = file.readlines() + for line in lst_to_write: + data[line[0]] = line[1] + with open(file_path, 'w') as file: + file.writelines(data) + + +if __name__ == '__main__': + main() From 887f05da562d63c332c74471fba0cdeab536fdb7 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Thu, 18 Mar 2021 22:22:36 -0400 Subject: [PATCH 19/44] [ADD] cloudflare deployement: change old ip to new ip, or delete DNS config - Script to get public ip - Documentation how to use with crontab --- doc/PRODUCTION.md | 25 +++++ requirements.txt | 3 + script/deployment/get_public_ip.py | 6 ++ script/deployment/update_dns_cloudflare.py | 106 +++++++++++++++++++++ 4 files changed, 140 insertions(+) create mode 100755 script/deployment/get_public_ip.py create mode 100755 script/deployment/update_dns_cloudflare.py diff --git a/doc/PRODUCTION.md b/doc/PRODUCTION.md index b2480e8..976658c 100644 --- a/doc/PRODUCTION.md +++ b/doc/PRODUCTION.md @@ -85,3 +85,28 @@ Caution, this delete user's home, it's irrevocable. ```bash ./script/delete_production.sh ``` + +# Update ip when public ip change with CloudFlare and crontab + +```bash +mkdir ~/.cloudflare +``` + +Edit ~/.cloudflare/cloudflare.cfg +``` +[PROFILE_NAME] +email=EMAIL +token=TOKEN +``` + +Add your cron +```bash +vim /etc/crontab +# Add +*/5 * * * * USER cd PATH && ./script/deployment/update_dns_cloudflare.py --profile PROFILE_NAME --zone_name CLOUDFLARE_ZONE_NAME --dns_name DNS_NAME --auto_sync +``` + +Check log with +```bash +sudo journalctl -feu cron +``` \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index e4bb4da..d3dae6c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -34,3 +34,6 @@ python-keystoneclient toml iscompatible pandas==1.2.0 + +# For deployment +cloudflare diff --git a/script/deployment/get_public_ip.py b/script/deployment/get_public_ip.py new file mode 100755 index 0000000..4711da6 --- /dev/null +++ b/script/deployment/get_public_ip.py @@ -0,0 +1,6 @@ +#!./.venv/bin/python +import requests + +r = requests.get(r'https://api.ipify.org') +ip = r.text +print(ip) diff --git a/script/deployment/update_dns_cloudflare.py b/script/deployment/update_dns_cloudflare.py new file mode 100755 index 0000000..cd7a678 --- /dev/null +++ b/script/deployment/update_dns_cloudflare.py @@ -0,0 +1,106 @@ +#!./.venv/bin/python +import argparse +import logging +import CloudFlare +import requests + +logging.basicConfig() +logging.getLogger().setLevel(logging.INFO) +_logger = logging.getLogger(__name__) + + +def get_config(): + """Parse command line arguments, extracting the config file name, + returning the union of config file and command line arguments + + :return: dict of config file settings and command line arguments + """ + + # TODO update description + parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description='''\ + Can update all old_ip to new_ip. + When auto_sync is enable: + Check zone and name on cloudflare and compare with public ip, update all old ip with new ip if different. + You need your profile in file ~/.cloudflare/cloudflare.cfg +''', + epilog='''\ +''' + ) + parser.add_argument('--profile', required=True, + help="The profile of CloudFlare, check ~/.cloudflare/cloudflare.cfg.") + parser.add_argument('--old_ip', required=False, help="Ip to search to update.") + parser.add_argument('--new_ip', required=False, help="Ip to replace the old ip.") + parser.add_argument('--dns_name', required=False, help="DNS name to output his ip and sync.") + parser.add_argument('--zone_name', required=False, help="The CloudFlare zone name to check.") + parser.add_argument('--delete', action="store_true") + parser.add_argument('--debug', action="store_true") + parser.add_argument('--raw', action="store_true") + parser.add_argument('--auto_sync', action="store_true", + help="Need this to use DNS name and zone name to sync public ip to CloudFlare.") + args = parser.parse_args() + return args + + +class ManageCloudFlare: + def __init__(self, profile, debug=False, raw=False): + self.cf = CloudFlare.CloudFlare(profile=profile, debug=debug, raw=raw) + self.raw = raw + + @staticmethod + def get_public_ip(): + r = requests.get(r'https://api.ipify.org') + ip = r.text + return ip + + def get_ip_cloudflare(self, zone_name, name): + """Return ip from a zone and domain""" + zone = self.cf.zones.get(params={'name': zone_name}) + lst_zone = [a.get("id") for a in zone] + for zone_id in lst_zone: + lst_result_dns = self.cf.zones.dns_records.get(zone_id) + for result_dns in lst_result_dns: + if result_dns.get("type") == "A" and result_dns.get("name") == name: + return result_dns.get("content") + + def edit_cloudflare(self, old_ip, delete=False, new_ip=""): + """Change ip of zone and name""" + + # TODO support smaller range + params = {'per_page': 500} + zones = self.cf.zones.get(params=params) + result = zones.get("result") if self.raw else zones + lst_zone = [a.get("id") for a in result] + for zone_id in lst_zone: + # dns_records = cf.zones.dns_records.export.get(zone_id) + result_dns = self.cf.zones.dns_records.get(zone_id) + dns_records = result_dns.get("result") if self.raw else result_dns + for dns in dns_records: + if dns.get("content") == old_ip: + if delete: + _logger.info(f"Delete {dns.get('name')}") + r = self.cf.zones.dns_records.delete(zone_id, dns.get("id")) + elif new_ip: + _logger.info(f"Update {dns.get('name')} with ip {new_ip}, old ip was {old_ip}") + dns_record = {'name': dns.get("name"), 'type': dns.get("type"), 'content': new_ip} + r = self.cf.zones.dns_records.post(zone_id, data=dns_record) + r = self.cf.zones.dns_records.delete(zone_id, dns.get("id")) + + +def main(): + config = get_config() + cl = ManageCloudFlare(config.profile, debug=config.debug) + if config.auto_sync: + configured_ip = cl.get_ip_cloudflare(config.zone_name, config.dns_name) + actual_ip = cl.get_public_ip() + if configured_ip != actual_ip: + cl.edit_cloudflare(configured_ip, new_ip=actual_ip) + else: + _logger.info(f"Nothing to do, same ip {actual_ip}") + else: + cl.edit_cloudflare(config.old_ip, delete=config.delete, new_ip=config.new_ip) + + +if __name__ == '__main__': + main() From fcd755b5b6cce066af543b25d99adc095284df81 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Sat, 20 Mar 2021 21:07:24 -0400 Subject: [PATCH 20/44] [ADD] maintainer-tools to autopep8, flake8 and pylint-odoo --- .flake8 | 13 +++++++++++++ manifest/default.dev.xml | 1 + requirements.txt | 8 ++++++++ script/install_locally.sh | 1 + script/install_locally_dev.sh | 7 +++++++ source_repo_addons.csv | 1 + 6 files changed, 31 insertions(+) create mode 100644 .flake8 diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..351bb72 --- /dev/null +++ b/.flake8 @@ -0,0 +1,13 @@ +[flake8] +max-line-length = 80 +max-complexity = 16 +# B = bugbear +# B9 = bugbear opinionated (incl line length) +select = C,E,F,W,B,B9 +# E203: whitespace before ':' (black behaviour) +# E501: flake8 line length (covered by bugbear B950) +# W503: line break before binary operator (black behaviour) +ignore = E203,E501,W503 +exclude = + ./.git + .eggs/ diff --git a/manifest/default.dev.xml b/manifest/default.dev.xml index 19219ae..bb6c1d9 100644 --- a/manifest/default.dev.xml +++ b/manifest/default.dev.xml @@ -75,6 +75,7 @@ + diff --git a/requirements.txt b/requirements.txt index d3dae6c..ee94530 100644 --- a/requirements.txt +++ b/requirements.txt @@ -30,6 +30,14 @@ voicent-python python-swiftclient python-keystoneclient +# For logical test +docutils==0.16 +flake8 +pylint-odoo +git+https://github.com/oca/pylint-odoo.git#egg=pylint-odoo +# oca-maintainers-tools +# git+https://github.com/OCA/maintainer-tools.git#egg=oca-maintainers-tools + # For updating poetry toml iscompatible diff --git a/script/install_locally.sh b/script/install_locally.sh index 362f5e9..e7d6c9f 100755 --- a/script/install_locally.sh +++ b/script/install_locally.sh @@ -155,6 +155,7 @@ if [[ ${EL_MINIMAL_ADDONS} = "False" ]]; then printf "${EL_HOME}/doc/itpp-labs_odoo-port-docs," >> ${EL_CONFIG_FILE} printf "${EL_HOME}/doc/itpp-labs_odoo-test-docs," >> ${EL_CONFIG_FILE} printf "${EL_HOME}/doc/odoo_documentation-user," >> ${EL_CONFIG_FILE} + printf "${EL_HOME}/script/OCA_maintainer-tools," >> ${EL_CONFIG_FILE} printf "${EL_HOME}/script/OCA_odoo-module-migrator," >> ${EL_CONFIG_FILE} fi printf "\n" >> ${EL_CONFIG_FILE} diff --git a/script/install_locally_dev.sh b/script/install_locally_dev.sh index 39afb4c..d5c78a9 100755 --- a/script/install_locally_dev.sh +++ b/script/install_locally_dev.sh @@ -6,3 +6,10 @@ # Update git-repo ./script/update_manifest_local_dev.sh + +# Install maintainer-tools +cd script/OCA_maintainer-tools +virtualenv env +. env/bin/activate +python setup.py install +#${VENV_PATH}/bin/pip install ./script/OCA_maintainer-tools/ diff --git a/source_repo_addons.csv b/source_repo_addons.csv index 1447f16..ff90149 100644 --- a/source_repo_addons.csv +++ b/source_repo_addons.csv @@ -125,6 +125,7 @@ https://github.com/itpp-labs/odoo-port-docs.git,doc,master, https://github.com/itpp-labs/odoo-test-docs.git,doc,master, https://github.com/odoo/documentation-user.git,doc,, https://github.com/OCA/odoo-module-migrator.git,script,master, +https://github.com/OCA/maintainer-tools.git,script,master, https://github.com/TechnoLibre/odoo-code-generator.git,addons,, https://github.com/TechnoLibre/odoo-code-generator-template.git,addons,, https://github.com/ERPLibre/ERPLibre_image_db.git,,, From 924a450b9ab68a75bab34da5330b7e30ffedd249 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Mon, 22 Mar 2021 04:08:53 -0400 Subject: [PATCH 21/44] [REM] Makefile remove test_code_generator_demo_portal --- Makefile | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Makefile b/Makefile index 63cad86..699dd7d 100644 --- a/Makefile +++ b/Makefile @@ -187,11 +187,6 @@ test_code_generator_template: db_restore_erplibre_base_db_template addons_instal .PHONY: test_code_generator_demo test_code_generator_demo: db_restore_erplibre_base_db_template addons_install_all_generated_demo clean_code_generator_template -.PHONY: test_code_generator_demo_portal -test_code_generator_demo_portal: db_restore_erplibre_base_db_code_generator - ./install_addon.sh code_generator code_generator_demo_portal - ./script/repo_revert_git_diff_date_from_code_generator.py - ########### # clean # ########### From 8078b68261d9501a350dfcbac708bd561248a773 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Mon, 22 Mar 2021 04:22:50 -0400 Subject: [PATCH 22/44] [ADD] documentation black, odoo-autopep8, prettier --- doc/DEVELOPMENT.md | 24 ++++++++++++++++++++++++ docker/Dockerfile | 4 +++- requirements.txt | 5 +++++ script/install_OSX_dependency.sh | 1 + script/install_debian_dependency.sh | 3 +++ script/maintenance/autopep8.sh | 6 ++++++ script/maintenance/black.sh | 5 +++++ script/maintenance/prettier.sh | 4 ++++ 8 files changed, 51 insertions(+), 1 deletion(-) create mode 100755 script/maintenance/autopep8.sh create mode 100755 script/maintenance/black.sh create mode 100755 script/maintenance/prettier.sh diff --git a/doc/DEVELOPMENT.md b/doc/DEVELOPMENT.md index 3de1dda..fcc92e3 100644 --- a/doc/DEVELOPMENT.md +++ b/doc/DEVELOPMENT.md @@ -139,3 +139,27 @@ Use this commit format: ```bash git commit -am "[#ticket] subject: short sentence" ``` + +# Format code +## Python +Use [black](https://github.com/psf/black) +```bash +./script/maintenance/black.sh ./addons/TechnoLibre_odoo-code-generator +``` + +Or if you prefer [oca-autopep8](https://github.com/psf/black) +```bash +./script/maintenance/autopep8.sh ./addons/TechnoLibre_odoo-code-generator +``` + +## HTML and css +Use [prettier](https://github.com/prettier/prettier) +```bash +./script/maintenance/prettier.sh ./addons/TechnoLibre_odoo-code-generator +``` + +## Javascript +Use [prettier](https://github.com/prettier/prettier) +```bash +./script/maintenance/prettier.sh --tab-width 4 ./addons/TechnoLibre_odoo-code-generator +``` diff --git a/docker/Dockerfile b/docker/Dockerfile index 5fe10c7..aa13444 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -15,7 +15,7 @@ RUN apt-get update \ fonts-noto-cjk \ gnupg \ libssl-dev \ - node-less \ + node-less \ npm \ python3-num2words \ python3-pip \ @@ -38,6 +38,8 @@ RUN apt-get update \ && apt-get install -y --no-install-recommends ./wkhtmltox.deb \ && rm -rf /var/lib/apt/lists/* wkhtmltox.deb +RUN npm i prettier + # install latest postgresql-client RUN echo 'deb http://apt.postgresql.org/pub/repos/apt/ buster-pgdg main' > /etc/apt/sources.list.d/pgdg.list \ && GNUPGHOME="$(mktemp -d)" \ diff --git a/requirements.txt b/requirements.txt index ee94530..9d87a8a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -37,6 +37,11 @@ pylint-odoo git+https://github.com/oca/pylint-odoo.git#egg=pylint-odoo # oca-maintainers-tools # git+https://github.com/OCA/maintainer-tools.git#egg=oca-maintainers-tools +xmlformatter +html5print +css-html-prettify +BeautifulSoup4 +black # For updating poetry toml diff --git a/script/install_OSX_dependency.sh b/script/install_OSX_dependency.sh index 3866f97..42c99bb 100755 --- a/script/install_OSX_dependency.sh +++ b/script/install_OSX_dependency.sh @@ -35,6 +35,7 @@ echo "\n---- Installing nodeJS NPM and rtlcss for LTR support ----" brew install nodejs npm openssl sudo npm install -g rtlcss sudo npm install -g less +sudo npm install -g prettier yes n|pyenv install 3.7.7 pyenv local 3.7.7 diff --git a/script/install_debian_dependency.sh b/script/install_debian_dependency.sh index 373dda7..dab9ab5 100755 --- a/script/install_debian_dependency.sh +++ b/script/install_debian_dependency.sh @@ -55,6 +55,9 @@ sudo apt-get install nodejs npm -y sudo npm install -g rtlcss sudo npm install -g less +echo -e "\n---- Test tool ----" +sudo npm install -g prettier + sudo ln -fs /usr/local/bin/lessc /usr/bin/lessc if [ ${EL_INSTALL_NGINX} = "True" ]; then diff --git a/script/maintenance/autopep8.sh b/script/maintenance/autopep8.sh new file mode 100755 index 0000000..9a3d506 --- /dev/null +++ b/script/maintenance/autopep8.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +# This will format all python file +# argument 1: directory or file to format +NPROC=$(nproc) +source ./script/OCA_maintainer-tools/env/bin/activate +oca-autopep8 -j ${NPROC} --max-line-length 100 -ari $@ diff --git a/script/maintenance/black.sh b/script/maintenance/black.sh new file mode 100755 index 0000000..2bb5324 --- /dev/null +++ b/script/maintenance/black.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# This will format all python file +# argument 1: directory or file to format +source ./.venv/bin/activate +black -l 100 -t py37 $@ diff --git a/script/maintenance/prettier.sh b/script/maintenance/prettier.sh new file mode 100755 index 0000000..38c5fbe --- /dev/null +++ b/script/maintenance/prettier.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +# This will format all js,css,html +# argument 1: directory or file to format +prettier --write $@ From ff5a47d97e3f8ed65bd84bcf7fb86117e1228f81 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Fri, 26 Mar 2021 01:56:47 -0400 Subject: [PATCH 23/44] [ADD] format when run test --- Makefile | 2 ++ requirements.txt | 1 + 2 files changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 699dd7d..5833652 100644 --- a/Makefile +++ b/Makefile @@ -180,9 +180,11 @@ addons_install_all_code_generator: ########## .PHONY: test_code_generator_generation test_code_generator_generation: db_restore_erplibre_base_db_code_generator addons_install_all_code_generator_demo clean_code_generator_template + ./script/maintenance/black.sh ./addons/TechnoLibre_odoo-code-generator-template/ .PHONY: test_code_generator_template test_code_generator_template: db_restore_erplibre_base_db_template addons_install_all_code_generator_template clean_code_generator_template + ./script/maintenance/black.sh ./addons/TechnoLibre_odoo-code-generator-template/ .PHONY: test_code_generator_demo test_code_generator_demo: db_restore_erplibre_base_db_template addons_install_all_generated_demo clean_code_generator_template diff --git a/requirements.txt b/requirements.txt index 9d87a8a..62244c6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -42,6 +42,7 @@ html5print css-html-prettify BeautifulSoup4 black +git+https://github.com/psf/black.git#egg=black # For updating poetry toml From 55e0aa5ef3240f0cef608ee50caf101e91684194 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Sat, 3 Apr 2021 03:20:40 -0400 Subject: [PATCH 24/44] [UPD] change odoo-saas-tool to saas-addons from it-projects-llc --- manifest/default.dev.xml | 2 +- script/install_locally.sh | 2 +- source_repo_addons.csv | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/manifest/default.dev.xml b/manifest/default.dev.xml index bb6c1d9..c598b67 100644 --- a/manifest/default.dev.xml +++ b/manifest/default.dev.xml @@ -106,7 +106,6 @@ - @@ -131,6 +130,7 @@ + diff --git a/script/install_locally.sh b/script/install_locally.sh index e7d6c9f..e921637 100755 --- a/script/install_locally.sh +++ b/script/install_locally.sh @@ -132,7 +132,7 @@ if [[ ${EL_MINIMAL_ADDONS} = "False" ]]; then printf "${EL_HOME}/addons/TechnoLibre_odoo-code-generator-template," >> ${EL_CONFIG_FILE} printf "${EL_HOME}/addons/camptocamp_odoo-cloud-platform," >> ${EL_CONFIG_FILE} printf "${EL_HOME}/addons/dhongu_deltatech," >> ${EL_CONFIG_FILE} - printf "${EL_HOME}/addons/it-projects-llc_odoo-saas-tools," >> ${EL_CONFIG_FILE} + printf "${EL_HOME}/addons/it-projects-llc_saas-addons," >> ${EL_CONFIG_FILE} printf "${EL_HOME}/addons/itpp-labs_access-addons," >> ${EL_CONFIG_FILE} printf "${EL_HOME}/addons/itpp-labs_pos-addons," >> ${EL_CONFIG_FILE} printf "${EL_HOME}/addons/itpp-labs_website-addons," >> ${EL_CONFIG_FILE} diff --git a/source_repo_addons.csv b/source_repo_addons.csv index ff90149..1364175 100644 --- a/source_repo_addons.csv +++ b/source_repo_addons.csv @@ -115,7 +115,7 @@ https://github.com/dhongu/deltatech.git,addons,, https://github.com/kinjal-sorathiya/Property-Management_odoo.git,addons,master, https://github.com/tegin/medical-fhir.git,addons,, https://github.com/odoomates/odooapps.git,addons,, -https://github.com/it-projects-llc/odoo-saas-tools.git,addons,, +https://github.com/it-projects-llc/saas-addons.git,addons,, https://github.com/itpp-labs/website-addons.git,addons,, https://github.com/itpp-labs/access-addons.git,addons,, https://github.com/itpp-labs/pos-addons.git,addons,, From 9d0300c3dad5321a08daeb8a595ae59a9b73c960 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Sun, 11 Apr 2021 03:03:51 -0400 Subject: [PATCH 25/44] [ADD] makefile format command and test_code_generator_generation_other --- Makefile | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Makefile b/Makefile index 5833652..9d16ced 100644 --- a/Makefile +++ b/Makefile @@ -182,6 +182,9 @@ addons_install_all_code_generator: test_code_generator_generation: db_restore_erplibre_base_db_code_generator addons_install_all_code_generator_demo clean_code_generator_template ./script/maintenance/black.sh ./addons/TechnoLibre_odoo-code-generator-template/ +.PHONY: test_code_generator_generation_other +test_code_generator_generation_other: db_restore_erplibre_base_db_code_generator addons_install_all_code_generator clean_code_generator_template + .PHONY: test_code_generator_template test_code_generator_template: db_restore_erplibre_base_db_template addons_install_all_code_generator_template clean_code_generator_template ./script/maintenance/black.sh ./addons/TechnoLibre_odoo-code-generator-template/ @@ -189,6 +192,20 @@ test_code_generator_template: db_restore_erplibre_base_db_template addons_instal .PHONY: test_code_generator_demo test_code_generator_demo: db_restore_erplibre_base_db_template addons_install_all_generated_demo clean_code_generator_template +############ +# format # +############ +.PHONY: format +format: format_code_generator format_code_generator_template + +.PHONY: format_code_generator +format_code_generator: + ./script/maintenance/black.sh ./addons/TechnoLibre_odoo-code-generator/ + +.PHONY: format_code_generator_template +format_code_generator_template: + ./script/maintenance/black.sh ./addons/TechnoLibre_odoo-code-generator-template/ + ########### # clean # ########### From 7f14bc8013b5db564f76d19ebf863fd4be7b27f8 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Fri, 23 Apr 2021 22:33:58 -0400 Subject: [PATCH 26/44] [ADD] script prettier xml format --- script/install_OSX_dependency.sh | 1 + script/install_debian_dependency.sh | 1 + script/maintenance/prettier_xml.sh | 4 ++++ 3 files changed, 6 insertions(+) create mode 100755 script/maintenance/prettier_xml.sh diff --git a/script/install_OSX_dependency.sh b/script/install_OSX_dependency.sh index 42c99bb..61756db 100755 --- a/script/install_OSX_dependency.sh +++ b/script/install_OSX_dependency.sh @@ -36,6 +36,7 @@ brew install nodejs npm openssl sudo npm install -g rtlcss sudo npm install -g less sudo npm install -g prettier +sudo npm install -g prettier @prettier/plugin-xml yes n|pyenv install 3.7.7 pyenv local 3.7.7 diff --git a/script/install_debian_dependency.sh b/script/install_debian_dependency.sh index dab9ab5..820eee1 100755 --- a/script/install_debian_dependency.sh +++ b/script/install_debian_dependency.sh @@ -57,6 +57,7 @@ sudo npm install -g less echo -e "\n---- Test tool ----" sudo npm install -g prettier +sudo npm install -g prettier @prettier/plugin-xml sudo ln -fs /usr/local/bin/lessc /usr/bin/lessc diff --git a/script/maintenance/prettier_xml.sh b/script/maintenance/prettier_xml.sh new file mode 100755 index 0000000..d29771b --- /dev/null +++ b/script/maintenance/prettier_xml.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +# This will format all xml +# argument 1: directory or file to format +prettier --xml-whitespace-sensitivity "ignore" --prose-wrap always --tab-width 4 --no-bracket-spacing --print-width 120 --write $@ From 203ca8268526534c6481bbbe12f9c462864902c1 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Sun, 25 Apr 2021 00:39:46 -0400 Subject: [PATCH 27/44] [REM] manifest dev: odoo-cloud-plateform is not anymore in base --- manifest/default.dev.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest/default.dev.xml b/manifest/default.dev.xml index c598b67..0013b55 100644 --- a/manifest/default.dev.xml +++ b/manifest/default.dev.xml @@ -92,7 +92,7 @@ - + From a3cc183e25708894a29cc8fb2c7479f04ae3ccda Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Thu, 13 May 2021 01:03:09 -0400 Subject: [PATCH 28/44] [ADD] migrate prod to test database --- doc/PRODUCTION.md | 3 ++- script/migrate_prod_to_test.sh | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100755 script/migrate_prod_to_test.sh diff --git a/doc/PRODUCTION.md b/doc/PRODUCTION.md index 976658c..c5971a3 100644 --- a/doc/PRODUCTION.md +++ b/doc/PRODUCTION.md @@ -62,9 +62,10 @@ cd /[EL_USER]/erplibre ## Move prod database to dev When moving prod database to your dev environment, you want to remove email servers and install user test to test the database. +Warning, this is not safe for production, you expose all data. Run: ```bash -./run.sh --stop-after-init -i user_test,disable_mail_server --dev all -d DATABASE +./script/migrate_prod_to_test.sh DATABASE ``` ## Update production diff --git a/script/migrate_prod_to_test.sh b/script/migrate_prod_to_test.sh new file mode 100755 index 0000000..21c1f63 --- /dev/null +++ b/script/migrate_prod_to_test.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +if [ $# -lt 1 ]; then + # TODO: print usage + echo "Missing database name" + exit 1 +fi +source ./.venv/bin/activate +python3 ./odoo/odoo-bin -c ./config.conf --limit-time-real 99999 --limit-time-cpu 99999 --stop-after-init -i user_test,disable_mail_server,disable_auto_backup --dev all -d $@ From bfd7826492c51c06370abb64f51e11f9900ca906 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Sun, 16 May 2021 17:53:27 -0400 Subject: [PATCH 29/44] [ADD] script open terminal to improve code generator development --- Makefile | 7 +++++++ script/open_terminal_code_generator.sh | 24 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100755 script/open_terminal_code_generator.sh diff --git a/Makefile b/Makefile index 9d16ced..a44beac 100644 --- a/Makefile +++ b/Makefile @@ -192,6 +192,13 @@ test_code_generator_template: db_restore_erplibre_base_db_template addons_instal .PHONY: test_code_generator_demo test_code_generator_demo: db_restore_erplibre_base_db_template addons_install_all_generated_demo clean_code_generator_template +############## +# terminal # +############## +.PHONY: open_terminal +open_terminal: + ./script/open_terminal_code_generator.sh + ############ # format # ############ diff --git a/script/open_terminal_code_generator.sh b/script/open_terminal_code_generator.sh new file mode 100755 index 0000000..45a80f0 --- /dev/null +++ b/script/open_terminal_code_generator.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +# Open a new gnome-terminal with different path on new tab +working_path=`readlink -f .` +paths=( +"${working_path}/" +"${working_path}/addons/TechnoLibre_odoo-code-generator" +"${working_path}/addons/TechnoLibre_odoo-code-generator-template" + +) +cmd_before="cd " +# when change directory, open a new tab with command to execute +cmd_after=";gnome-terminal --tab -- bash -c 'git status;bash';" +#cmd_after=";gnome-terminal --tab;" + +LONGCMD="" +for t in ${paths[@]}; do + LONGCMD+=${cmd_before}${t}${cmd_after} +done + +#echo $LONGCMD + +# Open all terminal from paths list +#echo "gnome-terminal --window -- bash -c \"${LONGCMD}\"" +gnome-terminal --window -- bash -c "${LONGCMD}" From 41e645d3fa2260f5e39601acff4ec4ff8c72c62c Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Sun, 23 May 2021 21:10:00 -0400 Subject: [PATCH 30/44] [UPD] black: reduce max length to 79 char and experimental-string-processing --- script/maintenance/black.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/maintenance/black.sh b/script/maintenance/black.sh index 2bb5324..d0811c1 100755 --- a/script/maintenance/black.sh +++ b/script/maintenance/black.sh @@ -2,4 +2,4 @@ # This will format all python file # argument 1: directory or file to format source ./.venv/bin/activate -black -l 100 -t py37 $@ +black -l 79 --experimental-string-processing -t py37 $@ From 6002309a68460fddf41e65cb46b73407cb9a3cf1 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Thu, 27 May 2021 01:47:32 -0400 Subject: [PATCH 31/44] [ADD] makefile generate code generation other and i18n - clean test to stash git before copying data - prettier_xml.sh in format --- Makefile | 16 ++++ script/make.sh | 4 + ...evert_git_diff_date_from_code_generator.py | 77 ++++++++++--------- 3 files changed, 61 insertions(+), 36 deletions(-) create mode 100755 script/make.sh diff --git a/Makefile b/Makefile index a44beac..a53694d 100644 --- a/Makefile +++ b/Makefile @@ -192,6 +192,16 @@ test_code_generator_template: db_restore_erplibre_base_db_template addons_instal .PHONY: test_code_generator_demo test_code_generator_demo: db_restore_erplibre_base_db_template addons_install_all_generated_demo clean_code_generator_template +.PHONY: test_code_generator_code +test_code_generator_code: clean_test + ./script/make.sh test_code_generator_template + ./script/make.sh test_code_generator_generation_other + +.PHONY: test_code_generator_code_i18n +test_code_generator_code_i18n: test_code_generator_code + ./script/make.sh test_code_generator_template + ./script/make.sh clean_code_generator_template + ############## # terminal # ############## @@ -208,10 +218,12 @@ format: format_code_generator format_code_generator_template .PHONY: format_code_generator format_code_generator: ./script/maintenance/black.sh ./addons/TechnoLibre_odoo-code-generator/ + #./script/maintenance/prettier_xml.sh ./addons/TechnoLibre_odoo-code-generator/ .PHONY: format_code_generator_template format_code_generator_template: ./script/maintenance/black.sh ./addons/TechnoLibre_odoo-code-generator-template/ + #./script/maintenance/prettier_xml.sh ./addons/TechnoLibre_odoo-code-generator-template/ ########### # clean # @@ -220,6 +232,10 @@ format_code_generator_template: clean_code_generator_template: ./script/repo_revert_git_diff_date_from_code_generator.py +.PHONY: clean_test +clean_test: + cd addons/OCA_server-tools; git stash; git clean -fd + ############ # docker # ############ diff --git a/script/make.sh b/script/make.sh new file mode 100755 index 0000000..c95d7cb --- /dev/null +++ b/script/make.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +echo "==$&%== Begin ${@}" +time make $@ +echo "==$&%== End ${@}" diff --git a/script/repo_revert_git_diff_date_from_code_generator.py b/script/repo_revert_git_diff_date_from_code_generator.py index 7a9793e..881cf89 100755 --- a/script/repo_revert_git_diff_date_from_code_generator.py +++ b/script/repo_revert_git_diff_date_from_code_generator.py @@ -35,42 +35,47 @@ def main(): config = get_config() # rex = r"\s+(?=\d{2}(?:\d{2})?-\d{1,2}-\d{1,2}\b)" rex = r"[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) (2[0-3]|[01][0-9]):[0-5][0-9]" - path = "./addons/TechnoLibre_odoo-code-generator-template" - repo = git.Repo(path) - supported_ext = [".xml", ".pot", ".po"] - for diff in repo.index.diff(None, create_patch=True): - # if diff.change_type == "M": - file_path = diff.a_path - filename, file_extension = os.path.splitext(file_path) - if file_extension in supported_ext: - file_real_path = os.path.join(path, diff.a_path) - if not os.path.isfile(file_real_path): - continue - str_diff = repo.git.diff(diff.a_path) - patch = PatchSet(str_diff) - for modified_file in patch.modified_files: - lst_to_write = [] - for hunk in modified_file: - nb_line_source = len(hunk.source) - nb_line_target = len(hunk.target) - if nb_line_source != nb_line_target: - # TODO support different line - continue - # try: - # assert nb_line_source == nb_line_target, f"Not the same line of diff:\n{str_diff}" - # except Exception as e: - # print(e) - for i in range(nb_line_source): - result_source = re.split(rex, hunk.source[i]) - if i > len(hunk.target): - result_target = re.split(rex, hunk.target[i]) - else: - result_target = "" - if len(result_source) > 1 or len(result_target) > 1: - line_to_change = hunk.target_start + i - 1 - lst_to_write.append((line_to_change, hunk.source[i][1:])) - # rewrite - rewrite(file_real_path, lst_to_write) + lst_path = [ + "./addons/TechnoLibre_odoo-code-generator-template", + "./addons/OCA_server-tools", + ] + for path in lst_path: + repo = git.Repo(path) + supported_ext = [".xml", ".pot", ".po"] + for diff in repo.index.diff(None, create_patch=True): + # if diff.change_type == "M": + file_path = diff.a_path + filename, file_extension = os.path.splitext(file_path) + if file_extension in supported_ext: + file_real_path = os.path.join(path, diff.a_path) + if not os.path.isfile(file_real_path): + continue + str_diff = repo.git.diff(diff.a_path) + patch = PatchSet(str_diff) + for modified_file in patch.modified_files: + lst_to_write = [] + for hunk in modified_file: + nb_line_source = len(hunk.source) + nb_line_target = len(hunk.target) + if nb_line_source != nb_line_target: + # TODO support different line + _logger.warning(f"Source nb line different of target nb line for file {path}/{file_path}.") + continue + # try: + # assert nb_line_source == nb_line_target, f"Not the same line of diff:\n{str_diff}" + # except Exception as e: + # print(e) + for i in range(nb_line_source): + result_source = re.split(rex, hunk.source[i]) + if i > len(hunk.target): + result_target = re.split(rex, hunk.target[i]) + else: + result_target = "" + if len(result_source) > 1 or len(result_target) > 1: + line_to_change = hunk.target_start + i - 1 + lst_to_write.append((line_to_change, hunk.source[i][1:])) + # rewrite + rewrite(file_real_path, lst_to_write) def rewrite(file_path, lst_to_write): From 863ad4f434e3df2d107bd057132b89cab0519d90 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Sun, 30 May 2021 22:27:16 -0400 Subject: [PATCH 32/44] [FIX] installation ubuntu poetry error - poetry use env python - makefile add make install to install dev - check return status in install_locally - support OCA_maintainer-tools in fresh installation --- Makefile | 3 ++ ignore_requirements.txt | 1 + pyproject.toml | 1 - script/install_debian_dependency.sh | 2 + script/install_locally.sh | 58 ++++++++++++++++++++--------- script/install_locally_dev.sh | 15 +++++++- script/install_locally_prod.sh | 9 +++++ 7 files changed, 69 insertions(+), 20 deletions(-) diff --git a/Makefile b/Makefile index a53694d..ca2bb35 100644 --- a/Makefile +++ b/Makefile @@ -51,6 +51,9 @@ run_code_generator: ############# # INSTALL # ############# +.PHONY: install +install:install_os install_dev + .PHONY: install_dev install_dev: ./script/install_locally_dev.sh diff --git a/ignore_requirements.txt b/ignore_requirements.txt index 601982d..2c61fea 100644 --- a/ignore_requirements.txt +++ b/ignore_requirements.txt @@ -13,3 +13,4 @@ xlsxwriter ldap pythonjsonlogger python-alipay-sdk +pyrfc diff --git a/pyproject.toml b/pyproject.toml index 653ec71..12b840b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -96,7 +96,6 @@ pymysql = "^1.0.2" pyotp = "^2.4.1" pyparsing = "2.1.10" pyproj = "^3.0.0" -pyrfc = "^0.1.2" pyserial = "3.1.1" pysftp = "^0.2.9" python-chess = "<0.24" diff --git a/script/install_debian_dependency.sh b/script/install_debian_dependency.sh index 820eee1..2dd617a 100755 --- a/script/install_debian_dependency.sh +++ b/script/install_debian_dependency.sh @@ -49,6 +49,8 @@ sudo su - postgres -c "createuser -s ${EL_USER}" 2> /dev/null || true echo -e "\n--- Installing debian dependency --" sudo apt-get install git build-essential wget libxslt-dev libzip-dev libldap2-dev libsasl2-dev libpng12-0 gdebi-core libffi-dev libbz2-dev -y sudo apt-get install libmariadbd-dev -y +# Dependencies for pyenv +sudo apt-get install make libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev liblzma-dev -y echo -e "\n---- Installing nodeJS NPM and rtlcss for LTR support ----" sudo apt-get install nodejs npm -y diff --git a/script/install_locally.sh b/script/install_locally.sh index e921637..a95a0eb 100755 --- a/script/install_locally.sh +++ b/script/install_locally.sh @@ -178,13 +178,20 @@ if [[ ! -d "./addons/addons" ]]; then fi PYENV_PATH=~/.pyenv -PYENV_VERSION_PATH=${PYENV_PATH}/versions/3.7.7 +PYTHON_VERSION=3.7.7 +PYENV_VERSION_PATH=${PYENV_PATH}/versions/${PYTHON_VERSION} PYTHON_EXEC=${PYENV_VERSION_PATH}/bin/python POETRY_PATH=~/.poetry VENV_PATH=./.venv +LOCAL_PYTHON_EXEC=${VENV_PATH}/bin/python VENV_REPO_PATH=${VENV_PATH}/repo POETRY_VERSION=1.0.10 +echo "Python path version home" +echo ${PYENV_VERSION_PATH} +echo "Python path version local" +echo ${LOCAL_PYTHON_EXEC} + if [[ ! -d "${PYENV_PATH}" ]]; then echo -e "\n---- Installing pyenv in ${PYENV_PATH} ----" curl -L https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash @@ -196,28 +203,37 @@ eval "$(pyenv init -)" eval "$(pyenv virtualenv-init -)" if [[ ! -d "${PYENV_VERSION_PATH}" ]]; then - echo -e "\n---- Installing python 3.7.7 with pyenv in ${PYENV_VERSION_PATH} ----" - yes n|pyenv install 3.7.7 + echo -e "\n---- Installing python ${PYTHON_VERSION} with pyenv in ${PYENV_VERSION_PATH} ----" + yes n|pyenv install ${PYTHON_VERSION} + if [[ $retVal -ne 0 ]]; then + echo "Error when installing pyenv" + exit 1 + fi fi -pyenv local 3.7.7 +pyenv local ${PYTHON_VERSION} + +if [[ ! -d ${VENV_PATH} ]]; then + echo -e "\n---- Create Virtual environment Python ----" + if [[ -e ${PYTHON_EXEC} ]]; then + ${PYTHON_EXEC} -m venv .venv + retVal=$? + if [[ $retVal -ne 0 ]]; then + echo "Virtual environment, error when creating .venv" + exit 1 + fi + else + echo "Missing pyenv, please refer installation guide." + exit 1 + fi +fi if [[ ! -d "${POETRY_PATH}" ]]; then # Delete directory ~/.poetry and .venv to force update to new version echo -e "\n---- Installing poetry for reliable python package ----" # curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | ${PYTHON_EXEC} curl -fsS -o get-poetry.py https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py - python get-poetry.py -y --preview --version ${POETRY_VERSION} -fi - -if [[ ! -d ${VENV_PATH} ]]; then - echo -e "\n---- Create Virtual environment Python ----" - if [[ -e ${PYTHON_EXEC} ]]; then - ${PYTHON_EXEC} -m venv .venv - else - echo "Missing pyenv, please refer installation guide." - exit 1 - fi + ${LOCAL_PYTHON_EXEC} get-poetry.py -y --preview --version ${POETRY_VERSION} fi # Install git-repo if missing @@ -232,9 +248,15 @@ fi echo -e "\n---- Installing poetry dependency ----" ${VENV_PATH}/bin/pip install --upgrade pip -#/home/"${USER}"/.poetry/bin/poetry env use ${PYTHON_EXEC} -source $HOME/.poetry/env -poetry install +# Force python instead of changing env +#/home/"${USER}"/.poetry/bin/poetry env use ${LOCAL_PYTHON_EXEC} +# source $HOME/.poetry/env +${LOCAL_PYTHON_EXEC} ~/.poetry/bin/poetry install +retVal=$? +if [[ $retVal -ne 0 ]]; then + echo "Poetry installation error." + exit 1 +fi # Delete artifacts created by pip, cause error in next "poetry install" rm -rf artifacts diff --git a/script/install_locally_dev.sh b/script/install_locally_dev.sh index d5c78a9..94e39dc 100755 --- a/script/install_locally_dev.sh +++ b/script/install_locally_dev.sh @@ -3,13 +3,26 @@ . ./env_var.sh ./script/install_locally.sh +retVal=$? +if [[ $retVal -ne 0 ]]; then + echo "Error ./script/install_locally.sh" + exit 1 +fi # Update git-repo ./script/update_manifest_local_dev.sh +if [[ $retVal -ne 0 ]]; then + echo "Error manifest update, check git-repo." + exit 1 +fi # Install maintainer-tools cd script/OCA_maintainer-tools -virtualenv env +# virtualenv is not installed by default +#virtualenv env +../../.venv/bin/python -m venv env . env/bin/activate +pip install setuptools-rust python setup.py install #${VENV_PATH}/bin/pip install ./script/OCA_maintainer-tools/ +cd - diff --git a/script/install_locally_prod.sh b/script/install_locally_prod.sh index f6898d5..f3d31c5 100755 --- a/script/install_locally_prod.sh +++ b/script/install_locally_prod.sh @@ -3,6 +3,15 @@ . ./env_var.sh ./script/install_locally.sh +retVal=$? +if [[ $retVal -ne 0 ]]; then + echo "Error ./script/install_locally.sh" + exit 1 +fi # Update git-repo ./script/update_manifest_prod.sh +if [[ $retVal -ne 0 ]]; then + echo "Error manifest update, check git-repo." + exit 1 +fi From 8a70d064d1c2c5c98401d23e6fbf18b446fae8f5 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Mon, 14 Jun 2021 04:11:46 -0400 Subject: [PATCH 33/44] [FIX] repo_revert_git_diff_date_from_code_generator: remove wrong lines in translation caused by ERPLibre structure --- ..._revert_git_diff_date_from_code_generator.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/script/repo_revert_git_diff_date_from_code_generator.py b/script/repo_revert_git_diff_date_from_code_generator.py index 881cf89..7318a5d 100755 --- a/script/repo_revert_git_diff_date_from_code_generator.py +++ b/script/repo_revert_git_diff_date_from_code_generator.py @@ -35,6 +35,7 @@ def main(): config = get_config() # rex = r"\s+(?=\d{2}(?:\d{2})?-\d{1,2}-\d{1,2}\b)" rex = r"[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) (2[0-3]|[01][0-9]):[0-5][0-9]" + # TODO support argument instead of hardcoded values lst_path = [ "./addons/TechnoLibre_odoo-code-generator-template", "./addons/OCA_server-tools", @@ -42,6 +43,7 @@ def main(): for path in lst_path: repo = git.Repo(path) supported_ext = [".xml", ".pot", ".po"] + translation_ext = [".pot", ".po"] for diff in repo.index.diff(None, create_patch=True): # if diff.change_type == "M": file_path = diff.a_path @@ -50,6 +52,21 @@ def main(): file_real_path = os.path.join(path, diff.a_path) if not os.path.isfile(file_real_path): continue + if file_extension in translation_ext: + is_modified = False + lst_write_data = [] + # Delete code expression path caused by ERPLibre architecture + with open(file_real_path, 'r') as file: + lst_data = file.readlines() + for data in lst_data: + if data.startswith("#: code:addons/addons/"): + is_modified = True + else: + lst_write_data.append(data) + if is_modified: + with open(file_real_path, 'w') as file: + file.writelines(lst_write_data) + str_diff = repo.git.diff(diff.a_path) patch = PatchSet(str_diff) for modified_file in patch.modified_files: From 1aa967fb6f0934024dfc3041ac3e298a17fb8456 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Tue, 9 Mar 2021 04:28:14 -0500 Subject: [PATCH 34/44] [ADD] Multilingual markdown, support doc/CODE_GENERATOR.md in FR and EN - Update README --- CHANGELOG.md | 3 +- Makefile | 5 + README.md | 11 +- doc/CODE_GENERATOR.base.md | 448 +++++++++++++++++++++++++++++++++++++ doc/CODE_GENERATOR.fr.md | 222 ++++++++++++++++++ doc/CODE_GENERATOR.md | 141 +++++++++--- script/install_locally.sh | 11 + 7 files changed, 805 insertions(+), 36 deletions(-) create mode 100644 doc/CODE_GENERATOR.base.md create mode 100644 doc/CODE_GENERATOR.fr.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cfd41e..22b480c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Added -- Code generator for Odoo module +- Code generator for Odoo module, depending of ERPLibre - Support map geoengine +- Multilingual markdown ### Changed diff --git a/Makefile b/Makefile index ca2bb35..5cafcd7 100644 --- a/Makefile +++ b/Makefile @@ -389,3 +389,8 @@ doc_user: .PHONY: doc_clean_user doc_clean_user: make -C doc/odoo_documentation-user clean + +# documentation markdown +.PHONY: doc_markdown +doc_markdown: + ./.venv/multilang_md.py $(shell pwd)/doc/CODE_GENERATOR.base.md \ No newline at end of file diff --git a/README.md b/README.md index 8f0ea32..3c25608 100644 --- a/README.md +++ b/README.md @@ -7,19 +7,18 @@ Clone the project git clone https://github.com/ERPLibre/ERPLibre.git cd ERPLibre ``` -Support Ubuntu 18.04 and OSX +Support Ubuntu 18.04, 20.04 and OSX. The installation duration is more than 30 minutes. ```bash -./script/install_dev.sh -./script/install_locally_prod.sh +make install ``` -Update your configuration if you need to run somehere than 127.0.0.1, file `config.conf` +Update your configuration if you need to run from another interface than 127.0.0.1, file `config.conf` ``` #xmlrpc_interface = 127.0.0.1 #netrpc_interface = 127.0.0.1 ``` -Run +Ready to execute ```bash -./run.sh +make run ``` ## Discover guide diff --git a/doc/CODE_GENERATOR.base.md b/doc/CODE_GENERATOR.base.md new file mode 100644 index 0000000..667d800 --- /dev/null +++ b/doc/CODE_GENERATOR.base.md @@ -0,0 +1,448 @@ + + + + + + +# How to generate code + + +# Comment générer du code + + +Never run this on production environment, this create circular dependencies and will cause frustration to clean damage. + +Ne jamais exécuter le générateur de code dans un environnement de production, il y a création de dépendance circulaire pouvant causer de la frustration à nettoyer tous les dommages. + + +``` +Modules +############ ################## ########## +# Template # -> # Code_Generator # -> # Module # +############ ################## ########## +``` + + +1. [A Template generates a Template or a Code_Generator.](#create-your-first-code_generator) +2. A Code_Generator generates a Module. +3. A Template reads a Module to generate a Code_Generator. + + +Il y a 3 types de module dans le contexte du générateur de code : +1. [A Template generates a Template or a Code_Generator.](#crer-votre-premier-code_generator) +2. Un Code_Generator génère un module. +3. Un Template lis un module pour générer un Code_Generator. + + +Warning, be careful to your code, always commit after a manipulation, because the mode enable_sync_code erase data, only the git will save you! + + +Attention pour ne pas écraser votre code, toujours commiter après une manipulation, l'utilisation du mode enable_sync_code peut effacer des données. Seul git vous sauvera! + + +TODO +Il y a 4 objectifs sur le générateur : ++ utilisation du générateur via l'interface web ++ créer un nouveau module, ++ modifier un module existant ++ exécuter les tests. + +test : +- code generator +- code generator extra (externe au repo template) +- template +- création d'un nouveau module direct ou chaine complète + - tester chaque étape de la création +- i18n (définir les différents cas) + +Suggestion de réduire les config avec make config_ pour les tests. + +TODO expliquer les modules/fonctionnalités actuellements supportés. portail WIP, snippet website WIP, cron, web vue tree+form, geoengine WIP, theme website, hook, db_servers WIP, exportation de donnée en module +TODO expliquer objectif des 4 libertés +TODO rechanger les termes pour : orcherstre + moule + module + + +## Manual generator with web interface + + +## Générateur de module avec l'interface web + + +TODO + + +At root path of ERPLibre git project, run: + + +Niveau intermédiaire. + +Pour utiliser le générateur de code, il faut ouvrir l'interface web qui permet la configuration du logiciel à générer. Un des choix suivants : + +Générateur de code de base : + +```bash +make addons_install_code_generator_basic +make run_code_generator +``` + + +Générateur de code avec fonctionnalités avancées : + +```bash +make addons_install_code_generator_featured +make run_code_generator +``` + + +Générateur de code avec fonctionnalités complètes : + +```bash +make addons_install_code_generator_full +make run_code_generator +``` + +Ouvrir le navigateur sur [http://localhost:8069](http://localhost:8069). Utilisateur `test` et mot de passe `test`. Une fois connecté, ouvrir sur [http://localhost:8069/web?debug=](http://localhost:8069/web?debug=) pour activer le déverminage. + +Ouvrir l'application `Code Generator` et créer un `Module`. Remplir les champs requis et générer avec `Action/Generate code`. + + +## Prepare a DB + + +## Préparer une BD + + +This will destroy and create database named `code_generator`. + + +Ceci va détruire et créer une base de donnée nommé `code_generator`. + + +```bash +make db_restore_erplibre_base_db_code_generator +``` + + +## Test code generator + + +## Tester le générateur de code + + +TODO + + +Tester la génération des modules internes du générateur, créant les démos à partir de leur générateur respectif. +```bash +make test_code_generator_generation +``` + + +## Create your first `Code_Generator` + + +## Créer votre premier `Code_Generator` + + +Edit [Code Generator Demo](./../addons/TechnoLibre_odoo-code-generator/code_generator_demo/hooks.py) and update `# TODO HUMAN:` + + +Modifier [Code Generator Demo](./../addons/TechnoLibre_odoo-code-generator/code_generator_demo/hooks.py) et mettre à jour `# TODO HUMAN:` + + +### Generate a `Template` + + +### Générer un `Template` + + +By default, `code_generator_demo` generate itself, `code_generator_demo`. + +Name your module begin with `MODULE_NAME = "code_generator_template_"` + +The value "enable_template_code_generator_demo" at `False` to create a new template module, else this will recreate `code_generator_demo`. + + +Par défaut, installer le module code_generator_demo va générer le module `code_generator_demo`. + +Nommer votre module en commençant par `MODULE_NAME = "code_generator_template_"` + + +Example, to generate the module `code_generator_template_demo_website_snippet`, change value: + + +Un exemple, générer le module `code_generator_template_demo_website_snippet`, changer la variable `value`: + + +```python +MODULE_NAME = "code_generator_template_demo_website_snippet" +[...] +value["enable_template_website_snippet_view"] = True +[...] +lst_depend = [ + "code_generator", + "code_generator_website_snippet", +] +``` + + +Generate new module, this will overwrite `code_generator_template_demo_website_snippet`: + + +Générer un nouveau module, ceci va écraser `code_generator_template_demo_website_snippet` : + + +```bash +make db_restore_erplibre_base_db_code_generator +make addons_install_code_generator_demo +``` + + +### Generate a Code_Generator (continue template) + + +### Générer un Code_Generator (suite de template) + + +Name your module begin with `MODULE_NAME = "code_generator_"` + + +Nommé votre module qui débute par `MODULE_NAME = "code_generator_"` + + +Continue the example, you generated the template `code_generator_template_demo_website_snippet`, this will overwrite `code_generator_demo_website_snippet`: + + +Pour continuer avec l'exemple, généré le template `code_generator_template_demo_website_snippet`, ceci va écraser `code_generator_demo_website_snippet`: + + +```bash +make db_restore_erplibre_base_db_template +./script/addons/install_addons.sh template code_generator_template_demo_website_snippet +``` + + +Go to section [Create your first module](#create-your-first-module) + + +Aller à la section [Créer votre premier module](#crer-votre-premier-module) + + +### Generate a Code_Generator_Demo + + +### Générer un Code_Generator_Demo + + +TODO validate this + + +Name your module begin with `MODULE_NAME = "code_generator_demo_"` + +Disable `enable_template_code_generator_demo` + + +Nommé votre module qui débute par `MODULE_NAME = "code_generator_demo_"` + +Désactiver la variable `enable_template_code_generator_demo` + + +```python +value["enable_template_code_generator_demo"] = False +``` + + +Continue the example, you generated the template `code_generator_template_demo_website_snippet`, this will overwrite `code_generator_demo_website_snippet`: + + +Pour continuer avec l'exemple, généré le template `code_generator_template_demo_website_snippet`, ceci va écraser `code_generator_demo_website_snippet`: + + +```bash +./script/addons/install_addons.sh code_generator code_generator_template_demo_website_snippet +``` + + +## Create your first Module + + +## Créer votre premier module + + +Continue example of code_generator_demo_website_snippet to generate your first module. Update next value: + + +Continuer avec l'exemple du `code_generator_demo_website_snippet` pour générer votre premier module. Mettre à jour les valeurs suivantes : + + +```python +"application": True, +"category_id": env.ref("base.module_category_website").id, +[...] +# Add dependencies +lst_depend = [ + "website", +] +``` + + +Generate your module: + + +Générer votre module : + + +```bash +./script/addons/install_addons.sh code_generator code_generator_demo_website_snippet +``` + + +Now, you can test it! Note, you cannot install a generated module with is code_generator associated, because duplicated +models! + + +Maintenant, vous pouvez le tester! Pour info, on ne peut pas installer un module généré avec son générateur de code associé, puisqu'il y a une duplication des modèles! + + + + +Il est maintenant possible de modifier les paramètres via l'interface manuelle pour ce module, puis le regénérer en effaçant la BD. Ajouter un modèle. + + +```bash +make db_restore_erplibre_base_db_code_generator +./script/addons/install_addons.sh code_generator code_generator_demo_website_snippet +``` + + + + +Faire la boucle d'amélioration, commiter le code pour avoir une traçabilité des changements. + +Ensuite, modifier la valeur `enable_sync_template` à `True` dans le fichier template, de l'exemple `code_generator_template_demo_website_snippet`. + + +```python +value["enable_sync_template"] = True +``` + + + + +Exécuter l'installation du template pour qu'il se synchronise sur le module généré. +```bash +make db_restore_erplibre_base_db_template +./script/addons/install_addons.sh template code_generator_template_demo_website_snippet +``` + + +Ready to test, generate your module: + + +Prêt à tester, générer le module : + + +```bash +# Optional, reset test database +make db_restore_erplibre_base_db_test +./script/addons/install_addons.sh test demo_website_snippet +``` + + +# How to generate i18n translation + + +# Comment générer les traductions i18n + + +You need a template and a module. Be sure you have this line in template: + + +Vous avez besoin d'un template et d'un module. Soyez certain que vous avez cette ligne dans le template : + + +```python +new_module_path = os.path.join(path_module_generate, new_module_name) +code_generator_writer.set_module_translator(new_module_name, new_module_path) +``` + + +First, install the module, example `demo_portal`, and after the template, example `code_generator_template_demo_portal`. + + +Premièrement, installer le module, par exemple `demo_portal`, et ensuite le template, par exemple `code_generator_template_demo_portal`. + + +```bash +make db_restore_erplibre_base_db_code_generator +./script/addons/install_addons.sh test demo_portal +./script/addons/install_addons.sh test code_generator_template_demo_portal +``` + + +# Sync Code_Generator fields from Module + + +# Synchroniser les champs du `Code_Generator` du module + + +This reduce time of programming a `Code_Generator` with sync module field with `Template`. + +You need a `Template`, a `Code_Generator` with his `Module`. Install the `Module` first in clean database and install `Template`, +this will generate the `Code_Generator`, use `enable_sync_template` at True. + +Example: + + +Ceci va permettre de réduire le temps de programmation d'un `Code_Generator` avec la synchronisation des champs de module avec `Template`. + +On a besoin d'un `Template`, un `Code_Generator` accompagné de son module. Installer le module en premier dans une base de donnée nettoyé et installer le `Template`, ceci va générer le `Code_Generator`, utiliser `enable_sync_template` à la valeur `True`. + +Exemple : + + +```bash +make db_restore_erplibre_base_db_code_generator +./script/addons/install_addons.sh test demo_portal +./script/addons/install_addons.sh test code_generator_template_demo_portal +``` + + +# Test the code generator + + +# Tester le générateur de code + + +TODO + + +Une bonne manière de tester un générateur de code est de valider qu'il génère le même code, il ne devient pas nécessaire de tester les fonctionnalités, puisque le comportement est la génération. + +Tester les générations simples : + + +```bash +make test_code_generator_generation +``` + + +TODO + + +Tester les générations extra : + + +```bash +make test_code_generator_generation_extra +``` + +TODO + + +Tester les générations des templates : + + +```bash +make test_code_generator_template +``` diff --git a/doc/CODE_GENERATOR.fr.md b/doc/CODE_GENERATOR.fr.md new file mode 100644 index 0000000..695d82d --- /dev/null +++ b/doc/CODE_GENERATOR.fr.md @@ -0,0 +1,222 @@ +# Comment générer du code + +Ne jamais exécuter le générateur de code dans un environnement de production, il y a création de dépendance circulaire pouvant causer de la frustration à nettoyer tous les dommages. + +``` +Modules +############ ################## ########## +# Template # -> # Code_Generator # -> # Module # +############ ################## ########## +``` + +Il y a 3 types de module dans le contexte du générateur de code : +1. [A Template generates a Template or a Code_Generator.](#crer-votre-premier-code_generator) +2. Un Code_Generator génère un module. +3. Un Template lis un module pour générer un Code_Generator. + +Attention pour ne pas écraser votre code, toujours commiter après une manipulation, l'utilisation du mode enable_sync_code peut effacer des données. Seul git vous sauvera! + +## Générateur de module avec l'interface web + +Niveau intermédiaire. + +Pour utiliser le générateur de code, il faut ouvrir l'interface web qui permet la configuration du logiciel à générer. Un des choix suivants : + +Générateur de code de base : +```bash +make addons_install_code_generator_basic +make run_code_generator +``` + +Générateur de code avec fonctionnalités avancées : +```bash +make addons_install_code_generator_featured +make run_code_generator +``` + +Générateur de code avec fonctionnalités complètes : +```bash +make addons_install_code_generator_full +make run_code_generator +``` + +Ouvrir le navigateur sur [http://localhost:8069](http://localhost:8069). Utilisateur `test` et mot de passe `test`. Une fois connecté, ouvrir sur [http://localhost:8069/web?debug=](http://localhost:8069/web?debug=) pour activer le déverminage. + +Ouvrir l'application `Code Generator` et créer un `Module`. Remplir les champs requis et générer avec `Action/Generate code`. + +## Préparer une BD + +Ceci va détruire et créer une base de donnée nommé `code_generator`. + +```bash +make db_restore_erplibre_base_db_code_generator +``` + +## Tester le générateur de code + +Tester la génération des modules internes du générateur, créant les démos à partir de leur générateur respectif. +```bash +make test_code_generator_generation +``` + +## Créer votre premier `Code_Generator` + +Modifier [Code Generator Demo](./../addons/TechnoLibre_odoo-code-generator/code_generator_demo/hooks.py) et mettre à jour `# TODO HUMAN:` + +### Générer un `Template` + +Par défaut, installer le module code_generator_demo va générer le module `code_generator_demo`. + +Nommer votre module en commençant par `MODULE_NAME = "code_generator_template_"` + +Un exemple, générer le module `code_generator_template_demo_website_snippet`, changer la variable `value`: + +```python +MODULE_NAME = "code_generator_template_demo_website_snippet" +[...] +value["enable_template_website_snippet_view"] = True +[...] +lst_depend = [ + "code_generator", + "code_generator_website_snippet", +] +``` + +Générer un nouveau module, ceci va écraser `code_generator_template_demo_website_snippet` : + +```bash +make db_restore_erplibre_base_db_code_generator +make addons_install_code_generator_demo +``` + +### Générer un Code_Generator (suite de template) + +Nommé votre module qui débute par `MODULE_NAME = "code_generator_"` + +Pour continuer avec l'exemple, généré le template `code_generator_template_demo_website_snippet`, ceci va écraser `code_generator_demo_website_snippet`: + +```bash +make db_restore_erplibre_base_db_template +./script/addons/install_addons.sh template code_generator_template_demo_website_snippet +``` + +Aller à la section [Créer votre premier module](#crer-votre-premier-module) + +### Générer un Code_Generator_Demo + +Nommé votre module qui débute par `MODULE_NAME = "code_generator_demo_"` + +Désactiver la variable `enable_template_code_generator_demo` + +```python +value["enable_template_code_generator_demo"] = False +``` + +Pour continuer avec l'exemple, généré le template `code_generator_template_demo_website_snippet`, ceci va écraser `code_generator_demo_website_snippet`: + +```bash +./script/addons/install_addons.sh code_generator code_generator_template_demo_website_snippet +``` + +## Créer votre premier module + +Continuer avec l'exemple du `code_generator_demo_website_snippet` pour générer votre premier module. Mettre à jour les valeurs suivantes : + +```python +"application": True, +"category_id": env.ref("base.module_category_website").id, +[...] +# Add dependencies +lst_depend = [ + "website", +] +``` + +Générer votre module : + +```bash +./script/addons/install_addons.sh code_generator code_generator_demo_website_snippet +``` + +Maintenant, vous pouvez le tester! Pour info, on ne peut pas installer un module généré avec son générateur de code associé, puisqu'il y a une duplication des modèles! + +Il est maintenant possible de modifier les paramètres via l'interface manuelle pour ce module, puis le regénérer en effaçant la BD. Ajouter un modèle. + +```bash +make db_restore_erplibre_base_db_code_generator +./script/addons/install_addons.sh code_generator code_generator_demo_website_snippet +``` + +Faire la boucle d'amélioration, commiter le code pour avoir une traçabilité des changements. + +Ensuite, modifier la valeur `enable_sync_template` à `True` dans le fichier template, de l'exemple `code_generator_template_demo_website_snippet`. + +```python +value["enable_sync_template"] = True +``` + +Exécuter l'installation du template pour qu'il se synchronise sur le module généré. +```bash +make db_restore_erplibre_base_db_template +./script/addons/install_addons.sh template code_generator_template_demo_website_snippet +``` + +Prêt à tester, générer le module : + +```bash +# Optional, reset test database +make db_restore_erplibre_base_db_test +./script/addons/install_addons.sh test demo_website_snippet +``` + +# Comment générer les traductions i18n + +Vous avez besoin d'un template et d'un module. Soyez certain que vous avez cette ligne dans le template : + +```python +new_module_path = os.path.join(path_module_generate, new_module_name) +code_generator_writer.set_module_translator(new_module_name, new_module_path) +``` + +Premièrement, installer le module, par exemple `demo_portal`, et ensuite le template, par exemple `code_generator_template_demo_portal`. + +```bash +make db_restore_erplibre_base_db_code_generator +./script/addons/install_addons.sh test demo_portal +./script/addons/install_addons.sh test code_generator_template_demo_portal +``` + +# Synchroniser les champs du `Code_Generator` du module + +Ceci va permettre de réduire le temps de programmation d'un `Code_Generator` avec la synchronisation des champs de module avec `Template`. + +On a besoin d'un `Template`, un `Code_Generator` accompagné de son module. Installer le module en premier dans une base de donnée nettoyé et installer le `Template`, ceci va générer le `Code_Generator`, utiliser `enable_sync_template` à la valeur `True`. + +Exemple : + +```bash +make db_restore_erplibre_base_db_code_generator +./script/addons/install_addons.sh test demo_portal +./script/addons/install_addons.sh test code_generator_template_demo_portal +``` + +# Tester le générateur de code + +Une bonne manière de tester un générateur de code est de valider qu'il génère le même code, il ne devient pas nécessaire de tester les fonctionnalités, puisque le comportement est la génération. + +Tester les générations simples : + +```bash +make test_code_generator_generation +``` + +Tester les générations extra : + +```bash +make test_code_generator_generation_extra +``` +Tester les générations des templates : + +```bash +make test_code_generator_template +``` diff --git a/doc/CODE_GENERATOR.md b/doc/CODE_GENERATOR.md index d31d832..f6c22c7 100644 --- a/doc/CODE_GENERATOR.md +++ b/doc/CODE_GENERATOR.md @@ -8,34 +8,62 @@ Modules # Template # -> # Code_Generator # -> # Module # ############ ################## ########## ``` -1. [A Template generates a Template or a Code_Generator.](Create your first code generator) + +1. [A Template generates a Template or a Code_Generator.](#create-your-first-code_generator) 2. A Code_Generator generates a Module. 3. A Template reads a Module to generate a Code_Generator. +Warning, be careful to your code, always commit after a manipulation, because the mode enable_sync_code erase data, only the git will save you! + +## Manual generator with web interface + +TODO + +```bash +make addons_install_code_generator_basic +make run_code_generator +``` + +```bash +make addons_install_code_generator_featured +make run_code_generator +``` + +```bash +make addons_install_code_generator_full +make run_code_generator +``` + +Ouvrir le navigateur sur [http://localhost:8069](http://localhost:8069). Utilisateur `test` et mot de passe `test`. Une fois connecté, ouvrir sur [http://localhost:8069/web?debug=](http://localhost:8069/web?debug=) pour activer le déverminage. + +Ouvrir l'application `Code Generator` et créer un `Module`. Remplir les champs requis et générer avec `Action/Generate code`. + ## Prepare a DB -This will destroy and create database named code_generator. +This will destroy and create database named `code_generator`. + ```bash make db_restore_erplibre_base_db_code_generator ``` -## Create your first Code_Generator +## Test code generator + +TODO + +## Create your first `Code_Generator` Edit [Code Generator Demo](./../addons/TechnoLibre_odoo-code-generator/code_generator_demo/hooks.py) and update `# TODO HUMAN:` -### Generate a Template +### Generate a `Template` -By default, code_generator_demo generate itself, code_generator_demo. +By default, `code_generator_demo` generate itself, `code_generator_demo`. Name your module begin with `MODULE_NAME = "code_generator_template_"` -The value "enable_template_code_generator_demo" at False to create a new template module, else this will recreate code_generator_demo. +The value "enable_template_code_generator_demo" at `False` to create a new template module, else this will recreate `code_generator_demo`. -```python -value["enable_template_code_generator_demo"] = True -``` +Example, to generate the module `code_generator_template_demo_website_snippet`, change value: -Example, to generate the module `code_generator_template_demo_website_snippet`, change value ```python MODULE_NAME = "code_generator_template_demo_website_snippet" [...] @@ -46,28 +74,47 @@ lst_depend = [ "code_generator_website_snippet", ] ``` -Generate new module, this will overwrite code_generator_template_demo_website_snippet: + +Generate new module, this will overwrite `code_generator_template_demo_website_snippet`: + ```bash +make db_restore_erplibre_base_db_code_generator make addons_install_code_generator_demo ``` -### Generate a Code_Generator +### Generate a Code_Generator (continue template) + +Name your module begin with `MODULE_NAME = "code_generator_"` + +Continue the example, you generated the template `code_generator_template_demo_website_snippet`, this will overwrite `code_generator_demo_website_snippet`: + +```bash +make db_restore_erplibre_base_db_template +./script/addons/install_addons.sh template code_generator_template_demo_website_snippet +``` + +Go to section [Create your first module](#create-your-first-module) + +### Generate a Code_Generator_Demo Name your module begin with `MODULE_NAME = "code_generator_demo_"` -Disable enable_template_code_generator_demo +Disable `enable_template_code_generator_demo` + ```python value["enable_template_code_generator_demo"] = False ``` -Continue the example, you generated the template `code_generator_template_demo_website_snippet`, this will overwrite code_generator_demo_website_snippet: +Continue the example, you generated the template `code_generator_template_demo_website_snippet`, this will overwrite `code_generator_demo_website_snippet`: + ```bash -./install_addon.sh code_generator code_generator_template_demo_website_snippet +./script/addons/install_addons.sh code_generator code_generator_template_demo_website_snippet ``` ## Create your first Module Continue example of code_generator_demo_website_snippet to generate your first module. Update next value: + ```python "application": True, "category_id": env.ref("base.module_category_website").id, @@ -79,45 +126,81 @@ lst_depend = [ ``` Generate your module: + ```bash -./install_addon.sh code_generator code_generator_demo_website_snippet +./script/addons/install_addons.sh code_generator code_generator_demo_website_snippet ``` -Now, you can test it! Note, you cannot install a generated module with is code_generator associated, because duplicated models! -Generate your module: +Now, you can test it! Note, you cannot install a generated module with is code_generator associated, because duplicated +models! + + +```bash +make db_restore_erplibre_base_db_code_generator +./script/addons/install_addons.sh code_generator code_generator_demo_website_snippet +``` + + +```python +value["enable_sync_template"] = True +``` + + +Ready to test, generate your module: + ```bash # Optional, reset test database make db_restore_erplibre_base_db_test -./install_addon.sh test demo_website_snippet +./script/addons/install_addons.sh test demo_website_snippet ``` # How to generate i18n translation -You need a template and a module. -Be sure you have this line in template: +You need a template and a module. Be sure you have this line in template: ```python new_module_path = os.path.join(path_module_generate, new_module_name) code_generator_writer.set_module_translator(new_module_name, new_module_path) ``` -First, install the module, example demo_portal, and after the template, example code_generator_template_demo_portal +First, install the module, example `demo_portal`, and after the template, example `code_generator_template_demo_portal`. + ```bash make db_restore_erplibre_base_db_code_generator -./install_addon.sh test demo_portal -./install_addon.sh test code_generator_template_demo_portal +./script/addons/install_addons.sh test demo_portal +./script/addons/install_addons.sh test code_generator_template_demo_portal ``` # Sync Code_Generator fields from Module -This reduce time of programming a Code_Generator with sync module field with Template. +This reduce time of programming a `Code_Generator` with sync module field with `Template`. -You need a Template, a Code_Generator with his Module. Install the Module first in clean database and install Template, this will generate the Code_generator, use `enable_sync_template` at True. +You need a `Template`, a `Code_Generator` with his `Module`. Install the `Module` first in clean database and install `Template`, +this will generate the `Code_Generator`, use `enable_sync_template` at True. + +Example: -Example ```bash make db_restore_erplibre_base_db_code_generator -./install_addon.sh test demo_portal -./install_addon.sh test code_generator_template_demo_portal +./script/addons/install_addons.sh test demo_portal +./script/addons/install_addons.sh test code_generator_template_demo_portal ``` +# Test the code generator + +TODO + +```bash +make test_code_generator_generation +``` + +TODO + +```bash +make test_code_generator_generation_extra +``` +TODO + +```bash +make test_code_generator_template +``` diff --git a/script/install_locally.sh b/script/install_locally.sh index a95a0eb..3b20639 100755 --- a/script/install_locally.sh +++ b/script/install_locally.sh @@ -185,6 +185,7 @@ POETRY_PATH=~/.poetry VENV_PATH=./.venv LOCAL_PYTHON_EXEC=${VENV_PATH}/bin/python VENV_REPO_PATH=${VENV_PATH}/repo +VENV_MULTILINGUAL_MARKDOWN_PATH=${VENV_PATH}/multilang_md.py POETRY_VERSION=1.0.10 echo "Python path version home" @@ -246,6 +247,16 @@ if [[ ! -f ${VENV_REPO_PATH} ]]; then sed -i "1 i ${PYTHON_HASHBANG}" ${VENV_REPO_PATH} fi +# Install Multilingual Markdown Generator if missing +if [[ ! -f ${VENV_MULTILINGUAL_MARKDOWN_PATH} ]]; then + echo "\n---- Install Multilingual Markdown Generator ----" + curl https://raw.githubusercontent.com/ERPLibre/multilingual-markdown/master/multilang_md.py > ${VENV_MULTILINGUAL_MARKDOWN_PATH} + chmod +x ${VENV_MULTILINGUAL_MARKDOWN_PATH} + sed -i 1d ${VENV_MULTILINGUAL_MARKDOWN_PATH} + PYTHON_HASHBANG="#!./.venv/bin/python" + sed -i "1 i ${PYTHON_HASHBANG}" ${VENV_MULTILINGUAL_MARKDOWN_PATH} +fi + echo -e "\n---- Installing poetry dependency ----" ${VENV_PATH}/bin/pip install --upgrade pip # Force python instead of changing env From 76a9a61b1e6b5994805b62dba9481b818749753f Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Sun, 27 Jun 2021 00:22:22 -0400 Subject: [PATCH 35/44] [ADD] make test --- Makefile | 102 +++++++++++------- README.md | 6 ++ install_addon.sh | 3 - reinstall_addon.sh | 3 - run.sh | 5 + script/addons/install_addons.sh | 7 ++ script/addons/reinstall_addons.sh | 8 ++ .../addons/uninstall_addons.sh | 0 .../check_git_change_code_generator.sh | 100 +++++++++++++++++ .../install_and_test_code_generator.sh | 25 +++++ script/maintenance/autopep8.sh | 7 +- script/maintenance/black.sh | 5 + script/maintenance/prettier.sh | 5 + script/maintenance/prettier_xml.sh | 5 + script/poetry_add_build_dependency.sh | 6 ++ 15 files changed, 244 insertions(+), 43 deletions(-) delete mode 100755 install_addon.sh delete mode 100755 reinstall_addon.sh create mode 100755 script/addons/install_addons.sh create mode 100755 script/addons/reinstall_addons.sh rename uninstall_addon.sh => script/addons/uninstall_addons.sh (100%) create mode 100755 script/code_generator/check_git_change_code_generator.sh create mode 100755 script/code_generator/install_and_test_code_generator.sh diff --git a/Makefile b/Makefile index 5cafcd7..d9f2062 100644 --- a/Makefile +++ b/Makefile @@ -46,6 +46,7 @@ run_test: .PHONY: run_code_generator run_code_generator: echo http://localhost:8069 + # -$(BROWSER) http://localhost:8069 ./run.sh --database code_generator ############# @@ -141,69 +142,98 @@ db_restore_erplibre_base_db_template: ######################### # Addons installation # ######################### +.PHONY: addons_install_code_generator_basic +addons_install_code_generator_basic: db_restore_erplibre_base_db_code_generator + ./script/addons/install_addons.sh code_generator code_generator + +.PHONY: addons_install_code_generator_featured +addons_install_code_generator_featured: addons_install_code_generator_basic + ./script/addons/install_addons.sh code_generator code_generator_cron,code_generator_hook,code_generator_portal + +.PHONY: addons_install_code_generator_full +addons_install_code_generator_full: addons_install_code_generator_featured + ./script/addons/install_addons.sh code_generator code_generator_db_servers,code_generator_website_snippet,code_generator_geoengine,code_generator_theme_website,code_generator_website_leaflet + .PHONY: addons_install_code_generator_demo addons_install_code_generator_demo: - ./install_addon.sh code_generator code_generator_demo + ./script/addons/install_addons.sh code_generator code_generator_demo .PHONY: addons_uninstall_code_generator_demo addons_uninstall_code_generator_demo: - ./uninstall_addon.sh code_generator code_generator_demo + ./script/addons/uninstall_addons.sh code_generator code_generator_demo .PHONY: addons_reinstall_code_generator_demo addons_reinstall_code_generator_demo: addons_uninstall_code_generator_demo addons_install_code_generator_demo .PHONY: addons_install_all_code_generator_demo -addons_install_all_code_generator_demo: - ./install_addon.sh code_generator code_generator_demo - ./install_addon.sh code_generator code_generator_demo_export_helpdesk - ./install_addon.sh code_generator code_generator_demo_internal - ./install_addon.sh code_generator code_generator_demo_portal - ./install_addon.sh code_generator code_generator_demo_theme_website - ./install_addon.sh code_generator code_generator_demo_website_leaflet - ./install_addon.sh code_generator code_generator_demo_website_snippet +addons_install_all_code_generator_demo: db_restore_erplibre_base_db_code_generator + ./script/addons/install_addons.sh code_generator code_generator_demo + ./script/addons/install_addons.sh code_generator code_generator_demo_export_helpdesk + ./script/addons/install_addons.sh code_generator code_generator_demo_internal + ./script/addons/install_addons.sh code_generator code_generator_demo_portal + ./script/addons/install_addons.sh code_generator code_generator_demo_theme_website + ./script/addons/install_addons.sh code_generator code_generator_demo_website_leaflet + ./script/addons/install_addons.sh code_generator code_generator_demo_website_snippet .PHONY: addons_install_all_code_generator_template addons_install_all_code_generator_template: - ./install_addon.sh template demo_portal,auto_backup - ./install_addon.sh template code_generator_template_demo_portal - ./install_addon.sh template code_generator_template_demo_sysadmin_cron + ./script/addons/install_addons.sh template demo_portal,auto_backup + ./script/addons/install_addons.sh template code_generator_template_demo_portal code_generator_template_demo_sysadmin_cron .PHONY: addons_install_all_generated_demo addons_install_all_generated_demo: - ./install_addon.sh template demo_export_helpdesk,demo_internal,demo_portal,demo_website_leaflet,demo_website_snippet + ./script/addons/install_addons.sh template demo_export_helpdesk,demo_internal,demo_portal,demo_website_leaflet,demo_website_snippet # TODO support installation theme with cli - #./install_addon.sh template theme_website_demo_code_generator + #./script/addons/install_addons.sh template theme_website_demo_code_generator .PHONY: addons_install_all_code_generator addons_install_all_code_generator: - ./install_addon.sh code_generator code_generator_auto_backup + ./script/addons/install_addons.sh code_generator code_generator_auto_backup ########## # test # ########## +.PHONY: test +test: test_format test_code_generator_generation test_code_generator_generation_extra test_code_generator_code_i18n test_code_generator_code_i18n_extra + +.PHONY: test_format +test_format: + ./script/maintenance/black.sh --check ./addons/TechnoLibre_odoo-code-generator/ + ./script/maintenance/black.sh --check ./addons/TechnoLibre_odoo-code-generator-template/ + .PHONY: test_code_generator_generation -test_code_generator_generation: db_restore_erplibre_base_db_code_generator addons_install_all_code_generator_demo clean_code_generator_template - ./script/maintenance/black.sh ./addons/TechnoLibre_odoo-code-generator-template/ +test_code_generator_generation: + ./script/code_generator/check_git_change_code_generator.sh ./addons/TechnoLibre_odoo-code-generator-template + time ./script/db_restore.py --database code_generator + ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo ./addons/TechnoLibre_odoo-code-generator-template + ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo_export_helpdesk ./addons/TechnoLibre_odoo-code-generator-template + ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo_internal ./addons/TechnoLibre_odoo-code-generator-template + ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo_portal ./addons/TechnoLibre_odoo-code-generator-template + ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo_theme_website ./addons/TechnoLibre_odoo-code-generator-template + ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo_website_leaflet ./addons/TechnoLibre_odoo-code-generator-template + ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo_website_snippet ./addons/TechnoLibre_odoo-code-generator-template -.PHONY: test_code_generator_generation_other -test_code_generator_generation_other: db_restore_erplibre_base_db_code_generator addons_install_all_code_generator clean_code_generator_template - -.PHONY: test_code_generator_template -test_code_generator_template: db_restore_erplibre_base_db_template addons_install_all_code_generator_template clean_code_generator_template - ./script/maintenance/black.sh ./addons/TechnoLibre_odoo-code-generator-template/ - -.PHONY: test_code_generator_demo -test_code_generator_demo: db_restore_erplibre_base_db_template addons_install_all_generated_demo clean_code_generator_template - -.PHONY: test_code_generator_code -test_code_generator_code: clean_test - ./script/make.sh test_code_generator_template - ./script/make.sh test_code_generator_generation_other +.PHONY: test_code_generator_generation_extra +test_code_generator_generation_extra: + ./script/code_generator/check_git_change_code_generator.sh ./addons/OCA_server-tools/auto_backup + time ./script/db_restore.py --database code_generator + ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_auto_backup ./addons/OCA_server-tools/auto_backup .PHONY: test_code_generator_code_i18n -test_code_generator_code_i18n: test_code_generator_code - ./script/make.sh test_code_generator_template - ./script/make.sh clean_code_generator_template +test_code_generator_code_i18n: + ./script/code_generator/check_git_change_code_generator.sh ./addons/TechnoLibre_odoo-code-generator-template + time ./script/db_restore.py --database template + ./script/addons/install_addons.sh template demo_portal + ./script/code_generator/install_and_test_code_generator.sh template code_generator_template_demo_portal ./addons/TechnoLibre_odoo-code-generator-template + +.PHONY: test_code_generator_code_i18n_extra +test_code_generator_code_i18n_extra: + ./script/code_generator/check_git_change_code_generator.sh ./addons/OCA_server-tools/auto_backup + time ./script/db_restore.py --database template + ./script/addons/install_addons.sh template auto_backup + ./script/code_generator/install_and_test_code_generator.sh template code_generator_template_demo_sysadmin_cron ./addons/TechnoLibre_odoo-code-generator-template + # To support i18n in auto_backup + ./script/code_generator/check_git_change_code_generator.sh ./addons/OCA_server-tools/auto_backup ############## # terminal # @@ -393,4 +423,4 @@ doc_clean_user: # documentation markdown .PHONY: doc_markdown doc_markdown: - ./.venv/multilang_md.py $(shell pwd)/doc/CODE_GENERATOR.base.md \ No newline at end of file + ./.venv/multilang_md.py $(shell pwd)/doc/CODE_GENERATOR.base.md diff --git a/README.md b/README.md index 3c25608..747d535 100644 --- a/README.md +++ b/README.md @@ -35,3 +35,9 @@ make run # git-repo To change repository like addons, see [GIT_REPO.md](doc/GIT_REPO.md) + +# Test +Execute ERPLibre test with his code generator. +```bash +time make test +``` diff --git a/install_addon.sh b/install_addon.sh deleted file mode 100755 index 697e520..0000000 --- a/install_addon.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash -./run.sh --no-http --stop-after-init -d $1 -i $2 -u $2 -echo "" diff --git a/reinstall_addon.sh b/reinstall_addon.sh deleted file mode 100755 index 8e420d4..0000000 --- a/reinstall_addon.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash -./uninstall_addon.sh $1 $2 -./install_addon.sh $1 $2 diff --git a/run.sh b/run.sh index 962ef3e..67d8bb3 100755 --- a/run.sh +++ b/run.sh @@ -1,3 +1,8 @@ #!/usr/bin/env bash source ./.venv/bin/activate python3 ./odoo/odoo-bin -c ./config.conf --limit-time-real 99999 --limit-time-cpu 99999 $@ +retVal=$? +if [[ $retVal -ne 0 ]]; then + echo "Error run.sh" + exit 1 +fi diff --git a/script/addons/install_addons.sh b/script/addons/install_addons.sh new file mode 100755 index 0000000..5c684c2 --- /dev/null +++ b/script/addons/install_addons.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +./run.sh --no-http --stop-after-init -d $1 -i $2 -u $2 +retVal=$? +if [[ $retVal -ne 0 ]]; then + echo "Error install_addons.sh" + exit 1 +fi diff --git a/script/addons/reinstall_addons.sh b/script/addons/reinstall_addons.sh new file mode 100755 index 0000000..4035d72 --- /dev/null +++ b/script/addons/reinstall_addons.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +./script/addons/uninstall_addons.sh $1 $2 +./script/addons/install_addons.sh $1 $2 +retVal=$? +if [[ $retVal -ne 0 ]]; then + echo "Error reinstall_addons.sh" + exit 1 +fi diff --git a/uninstall_addon.sh b/script/addons/uninstall_addons.sh similarity index 100% rename from uninstall_addon.sh rename to script/addons/uninstall_addons.sh diff --git a/script/code_generator/check_git_change_code_generator.sh b/script/code_generator/check_git_change_code_generator.sh new file mode 100755 index 0000000..f0c5e69 --- /dev/null +++ b/script/code_generator/check_git_change_code_generator.sh @@ -0,0 +1,100 @@ +#!/usr/bin/env bash +# REF: https://stackoverflow.com/a/28938235 +# Reset +Color_Off='\033[0m' # Text Reset + +# Regular Colors +Black='\033[0;30m' # Black +Red='\033[0;31m' # Red +Green='\033[0;32m' # Green +Yellow='\033[0;33m' # Yellow +Blue='\033[0;34m' # Blue +Purple='\033[0;35m' # Purple +Cyan='\033[0;36m' # Cyan +White='\033[0;37m' # White + +# Bold +BBlack='\033[1;30m' # Black +BRed='\033[1;31m' # Red +BGreen='\033[1;32m' # Green +BYellow='\033[1;33m' # Yellow +BBlue='\033[1;34m' # Blue +BPurple='\033[1;35m' # Purple +BCyan='\033[1;36m' # Cyan +BWhite='\033[1;37m' # White + +# Underline +UBlack='\033[4;30m' # Black +URed='\033[4;31m' # Red +UGreen='\033[4;32m' # Green +UYellow='\033[4;33m' # Yellow +UBlue='\033[4;34m' # Blue +UPurple='\033[4;35m' # Purple +UCyan='\033[4;36m' # Cyan +UWhite='\033[4;37m' # White + +# Background +On_Black='\033[40m' # Black +On_Red='\033[41m' # Red +On_Green='\033[42m' # Green +On_Yellow='\033[43m' # Yellow +On_Blue='\033[44m' # Blue +On_Purple='\033[45m' # Purple +On_Cyan='\033[46m' # Cyan +On_White='\033[47m' # White + +# High Intensity +IBlack='\033[0;90m' # Black +IRed='\033[0;91m' # Red +IGreen='\033[0;92m' # Green +IYellow='\033[0;93m' # Yellow +IBlue='\033[0;94m' # Blue +IPurple='\033[0;95m' # Purple +ICyan='\033[0;96m' # Cyan +IWhite='\033[0;97m' # White + +# Bold High Intensity +BIBlack='\033[1;90m' # Black +BIRed='\033[1;91m' # Red +BIGreen='\033[1;92m' # Green +BIYellow='\033[1;93m' # Yellow +BIBlue='\033[1;94m' # Blue +BIPurple='\033[1;95m' # Purple +BICyan='\033[1;96m' # Cyan +BIWhite='\033[1;97m' # White + +# High Intensity backgrounds +On_IBlack='\033[0;100m' # Black +On_IRed='\033[0;101m' # Red +On_IGreen='\033[0;102m' # Green +On_IYellow='\033[0;103m' # Yellow +On_IBlue='\033[0;104m' # Blue +On_IPurple='\033[0;105m' # Purple +On_ICyan='\033[0;106m' # Cyan +On_IWhite='\033[0;107m' # White + +# TODO support argument to test only specified path + +check_git() { + REP=$1 + cd ${REP} + + output=$(git status --porcelain) + if [ -z "$output" ]; then + echo "PASS - ${REP}" + else + echo -e "${Red}FAIL - ${REP}${Color_Off}" + echo -e "${BRed}${output}${Color_Off}" + cd - >/dev/null + exit 1 + fi + + cd - >/dev/null +} + +if [ $# -gt 0 ]; then + check_git "$1" +else + # check_git "./addons/TechnoLibre_odoo-code-generator" + check_git "./addons/TechnoLibre_odoo-code-generator-template" +fi diff --git a/script/code_generator/install_and_test_code_generator.sh b/script/code_generator/install_and_test_code_generator.sh new file mode 100755 index 0000000..9290906 --- /dev/null +++ b/script/code_generator/install_and_test_code_generator.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +# $1 is database name +# $2 is module name +# $3 is directory path to check + +./script/addons/install_addons.sh $1 $2 +retVal=$? +if [[ $retVal -ne 0 ]]; then + echo "Error ./script/addons/install_addons.sh ${1} ${2}" + exit 1 +fi +./script/repo_revert_git_diff_date_from_code_generator.py +# Remove pot and po diff +cd $3 +BRANCH=$(git branch --show-current) +git restore --source="${BRANCH}" "*.po*" +cd - +./script/maintenance/black.sh $3 +echo "TEST ${2}" +./script/code_generator/check_git_change_code_generator.sh $3 +retVal=$? +if [[ $retVal -ne 0 ]]; then + echo "Error ./script/code_generator/check_git_change_code_generator.sh" + exit 1 +fi diff --git a/script/maintenance/autopep8.sh b/script/maintenance/autopep8.sh index 9a3d506..7042148 100755 --- a/script/maintenance/autopep8.sh +++ b/script/maintenance/autopep8.sh @@ -3,4 +3,9 @@ # argument 1: directory or file to format NPROC=$(nproc) source ./script/OCA_maintainer-tools/env/bin/activate -oca-autopep8 -j ${NPROC} --max-line-length 100 -ari $@ +oca-autopep8 -j ${NPROC} --max-line-length 79 -ari $@ +retVal=$? +if [[ $retVal -ne 0 ]]; then + echo "Error oca-autopep8 format" + exit 1 +fi diff --git a/script/maintenance/black.sh b/script/maintenance/black.sh index d0811c1..357531b 100755 --- a/script/maintenance/black.sh +++ b/script/maintenance/black.sh @@ -3,3 +3,8 @@ # argument 1: directory or file to format source ./.venv/bin/activate black -l 79 --experimental-string-processing -t py37 $@ +retVal=$? +if [[ $retVal -ne 0 ]]; then + echo "Error black format" + exit 1 +fi diff --git a/script/maintenance/prettier.sh b/script/maintenance/prettier.sh index 38c5fbe..b7f22c3 100755 --- a/script/maintenance/prettier.sh +++ b/script/maintenance/prettier.sh @@ -2,3 +2,8 @@ # This will format all js,css,html # argument 1: directory or file to format prettier --write $@ +retVal=$? +if [[ $retVal -ne 0 ]]; then + echo "Error prettier format" + exit 1 +fi diff --git a/script/maintenance/prettier_xml.sh b/script/maintenance/prettier_xml.sh index d29771b..85237e8 100755 --- a/script/maintenance/prettier_xml.sh +++ b/script/maintenance/prettier_xml.sh @@ -2,3 +2,8 @@ # This will format all xml # argument 1: directory or file to format prettier --xml-whitespace-sensitivity "ignore" --prose-wrap always --tab-width 4 --no-bracket-spacing --print-width 120 --write $@ +retVal=$? +if [[ $retVal -ne 0 ]]; then + echo "Error prettier format" + exit 1 +fi diff --git a/script/poetry_add_build_dependency.sh b/script/poetry_add_build_dependency.sh index ed6c928..163820a 100755 --- a/script/poetry_add_build_dependency.sh +++ b/script/poetry_add_build_dependency.sh @@ -3,3 +3,9 @@ source $HOME/.poetry/env poetry add -vv $(grep -v ";" ./.venv/build_dependency.txt | grep -v "*" ) # poetry add -vv $(grep -v ";" ./.venv/build_dependency.txt | grep -v "*" | sed 's/==/@^/' ) # poetry export -f ./.venv/build_dependency.txt --dev | poetry run -- pip install -r /dev/stdin +retVal=$? +if [[ $retVal -ne 0 ]]; then + echo "Error ./script/poetry_add_build_dependency.sh" + cat ./.venv/build_dependency.txt + exit 1 +fi From ebbb2e86197aa0d7fd9f4a0e96ead0e50b2f5c89 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Sun, 27 Jun 2021 00:22:51 -0400 Subject: [PATCH 36/44] [UPD] poetry dependencies update --- doc/POETRY.md | 2 + poetry.lock | 1338 +++++++++++++++++++++++++-------------- pyproject.toml | 74 ++- requirements.txt | 13 +- script/poetry_update.py | 30 +- 5 files changed, 949 insertions(+), 508 deletions(-) diff --git a/doc/POETRY.md b/doc/POETRY.md index 60629dc..df94ae7 100644 --- a/doc/POETRY.md +++ b/doc/POETRY.md @@ -6,6 +6,8 @@ Add your dependencies in file [requirements.txt](../requirements.txt) and run sc ``` This will search all `requirements.txt` files and update `pyproject.toml` and it will update poetry +Priority dependencies in ./requirements.txt, after it's ./odoo/requirements.txt, after it's highest version values. + TODO add option to only add missing dependencies and ignore update. ## Add manually dependencies diff --git a/poetry.lock b/poetry.lock index 86e99a8..982ad3a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -47,12 +47,12 @@ description = "Bash tab completion for argparse" name = "argcomplete" optional = false python-versions = "*" -version = "1.12.2" +version = "1.12.3" [package.dependencies] [package.dependencies.importlib-metadata] python = ">=3.7,<3.8" -version = ">=0.23,<4" +version = ">=0.23,<5" [package.extras] test = ["coverage", "flake8", "pexpect", "wheel"] @@ -84,6 +84,22 @@ version = "0.0.8" [package.dependencies] requests = "*" +[[package]] +category = "main" +description = "An abstract syntax tree for Python with inference support." +name = "astroid" +optional = false +python-versions = ">=3.6" +version = "2.5" + +[package.dependencies] +lazy-object-proxy = ">=1.4.0" +wrapt = ">=1.11,<1.13" + +[package.dependencies.typed-ast] +python = "<3.8" +version = ">=1.4.0,<1.5" + [[package]] category = "main" description = "Classes Without Boilerplate" @@ -130,15 +146,51 @@ description = "Screen-scraping library" name = "beautifulsoup4" optional = false python-versions = "*" -version = "4.9.1" +version = "4.9.3" [package.dependencies] -soupsieve = [">1.2", "<2.0"] +[package.dependencies.soupsieve] +python = ">=3.0" +version = ">1.2" [package.extras] html5lib = ["html5lib"] lxml = ["lxml"] +[[package]] +category = "main" +description = "The uncompromising code formatter." +name = "black" +optional = false +python-versions = ">=3.6.2" +version = "21.6b0" + +[package.dependencies] +appdirs = "*" +click = ">=7.1.2" +mypy_extensions = ">=0.4.3" +pathspec = ">=0.8.1,<1" +regex = ">=2020.1.8" +toml = ">=0.10.1" + +[package.dependencies.typed-ast] +python = "<3.8" +version = ">=1.4.2" + +[package.dependencies.typing_extensions] +python = "<3.8" +version = ">=3.7.4" + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.6.0)", "aiohttp-cors (>=0.4.0)"] +python2 = ["typed-ast (>=1.4.2)"] +uvloop = ["uvloop (>=0.15.2)"] + +[package.source] +reference = "93c10bf9ebccf8d7cc686b0b9579f2e5e41c5328" +type = "git" +url = "https://github.com/psf/black.git" [[package]] category = "main" description = "Interactive plots and applications in the browser from Python" @@ -157,14 +209,6 @@ python-dateutil = ">=2.1" six = ">=1.5.2" tornado = ">=4.3" -[[package]] -category = "main" -description = "Amazon Web Services Library" -name = "boto" -optional = false -python-versions = "*" -version = "2.49.0" - [[package]] category = "main" description = "The AWS SDK for Python" @@ -184,10 +228,10 @@ description = "Low-level, data-driven core of boto 3." name = "botocore" optional = false python-versions = "*" -version = "1.12.253" +version = "1.12.191" [package.dependencies] -docutils = ">=0.10,<0.16" +docutils = ">=0.10" jmespath = ">=0.7.1,<1.0.0" [package.dependencies.python-dateutil] @@ -212,7 +256,7 @@ description = "Extensible memoizing collections and decorators" name = "cachetools" optional = false python-versions = "~=3.5" -version = "4.2.0" +version = "4.2.2" [[package]] category = "main" @@ -220,7 +264,7 @@ description = "Lightweight, extensible schema and data validation tool for Pytho name = "cerberus" optional = false python-versions = ">=2.7" -version = "1.3.2" +version = "1.3.4" [package.dependencies] setuptools = "*" @@ -257,8 +301,29 @@ category = "main" description = "Composable command line interface toolkit" name = "click" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "7.1.2" +python-versions = ">=3.6" +version = "8.0.1" + +[package.dependencies] +colorama = "*" + +[package.dependencies.importlib-metadata] +python = "<3.8" +version = "*" + +[[package]] +category = "main" +description = "Python wrapper for the Cloudflare v4 API" +name = "cloudflare" +optional = false +python-versions = "*" +version = "2.8.15" + +[package.dependencies] +beautifulsoup4 = "*" +jsonlines = "*" +pyyaml = "*" +requests = "*" [[package]] category = "main" @@ -276,20 +341,6 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" version = "0.4.4" -[[package]] -category = "main" -description = "Colored terminal output for Python's logging module" -name = "coloredlogs" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "14.0" - -[package.dependencies] -humanfriendly = ">=7.1" - -[package.extras] -cron = ["capturer (>=2.4)"] - [[package]] category = "main" description = "Compressed Rich Text Format (RTF) compression and decompression package" @@ -318,6 +369,17 @@ idna = ["idna (>=2.1)"] pep8test = ["flake8", "flake8-import-order", "pep8-naming"] test = ["pytest (>=3.6.0,<3.9.0 || >3.9.0,<3.9.1 || >3.9.1,<3.9.2 || >3.9.2)", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,<3.79.2 || >3.79.2)"] +[[package]] +category = "main" +description = "StandAlone Async cross-platform Prettifier Beautifier for the Web." +name = "css-html-prettify" +optional = false +python-versions = ">=3.6" +version = "2.5.5" + +[package.dependencies] +beautifulsoup4 = "*" + [[package]] category = "main" description = "cssselect parses CSS3 Selectors and translates them to XPath 1.0" @@ -351,7 +413,7 @@ description = "The Cython compiler for writing C extensions for the Python langu name = "cython" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -version = "0.29.21" +version = "0.29.23" [[package]] category = "main" @@ -447,8 +509,8 @@ category = "main" description = "Docutils -- Python Documentation Utilities" name = "docutils" optional = false -python-versions = "*" -version = "0.12" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "0.16" [[package]] category = "main" @@ -462,18 +524,37 @@ version = "2.1.5" lxml = "*" requests = "*" +[[package]] +category = "main" +description = "Additional EBCDIC codecs" +name = "ebcdic" +optional = false +python-versions = "*" +version = "1.1.1" + [[package]] category = "main" description = "A robust email syntax and deliverability validation library for Python 2.x/3.x." name = "email-validator" optional = false -python-versions = "*" -version = "1.1.2" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +version = "1.1.3" [package.dependencies] dnspython = ">=1.15.0" idna = ">=2.0.0" +[[package]] +category = "main" +description = "Emoji for Python" +name = "emoji" +optional = false +python-versions = "*" +version = "1.2.0" + +[package.extras] +dev = ["pytest", "coverage", "coveralls"] + [[package]] category = "main" description = "Discover and load entry points from installed packages." @@ -496,7 +577,7 @@ description = "Python library to manipulate ESC/POS Printers" name = "escpos" optional = false python-versions = ">=3.5" -version = "1.8" +version = "1.9" [package.dependencies] Pillow = ">=2.0" @@ -521,59 +602,33 @@ optional = false python-versions = "*" version = "1.0.1" -[[package]] -category = "main" -description = "Programmer friendly subprocess wrapper" -name = "executor" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "23.1" - -[package.dependencies] -coloredlogs = ">=3.5" -fasteners = ">=0.14.1" -humanfriendly = ">=8.0" -property-manager = ">=3.0" -six = ">=1.9.0" - [[package]] category = "main" description = "Extracts emails and attachments saved in Microsoft Outlook's .msg files" name = "extract-msg" optional = false python-versions = "*" -version = "0.28.0" +version = "0.28.7" [package.dependencies] compressed-rtf = ">=1.0.6" +ebcdic = ">=1.1.1" imapclient = "2.1.0" olefile = ">=0.46" tzlocal = ">=2.1" [[package]] category = "main" -description = "Factur-X: electronic invoicing standard for Germany & France" +description = "Factur-X and Order-X: electronic invoicing and ordering standards" name = "factur-x" optional = false python-versions = "*" -version = "1.12" +version = "2.3" [package.dependencies] PyPDF4 = "*" lxml = "*" -[[package]] -category = "main" -description = "A python package that provides useful locks." -name = "fasteners" -optional = false -python-versions = "*" -version = "0.15" - -[package.dependencies] -monotonic = ">=0.1" -six = "*" - [[package]] category = "main" description = "Universal feed parser, handles RSS 0.9x, RSS 1.0, RSS 2.0, CDF, Atom 0.3, and Atom 1.0 feeds" @@ -582,6 +637,23 @@ optional = false python-versions = "*" version = "5.2.1" +[[package]] +category = "main" +description = "the modular source code checker: pep8 pyflakes and co" +name = "flake8" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +version = "3.9.2" + +[package.dependencies] +mccabe = ">=0.6.0,<0.7.0" +pycodestyle = ">=2.7.0,<2.8.0" +pyflakes = ">=2.3.0,<2.4.0" + +[package.dependencies.importlib-metadata] +python = "<3.8" +version = "*" + [[package]] category = "main" description = "Let your Python tests travel through time" @@ -688,14 +760,38 @@ version = "2016.9.19" [[package]] category = "main" -description = "Human friendly output for text interfaces using Python" -name = "humanfriendly" +description = "HTML parser based on the WHATWG HTML specification" +name = "html5lib" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "8.2" +version = "1.1" [package.dependencies] -pyreadline = "*" +six = ">=1.9" +webencodings = "*" + +[package.extras] +all = ["genshi", "chardet (>=2.2)", "lxml"] +chardet = ["chardet (>=2.2)"] +genshi = ["genshi"] +lxml = ["lxml"] + +[[package]] +category = "main" +description = "HTML5, CSS, Javascript Pretty Print" +name = "html5print" +optional = false +python-versions = "*" +version = "0.1.2" + +[package.dependencies] +beautifulsoup4 = ">=4.3.2" +chardet = ">=2.2.1" +html5lib = ">=0.999" +ply = "3.4" +requests = ">=2.3.5" +slimit = ">=0.8.1" +tinycss2 = ">=0.4" [[package]] category = "main" @@ -761,7 +857,7 @@ description = "Python parser to extract data from pdf invoice" name = "invoice2data" optional = false python-versions = "*" -version = "0.3.5" +version = "0.3.6" [package.dependencies] chardet = "*" @@ -770,6 +866,9 @@ pillow = "*" pyyaml = "*" unidecode = "*" +[package.extras] +test = ["pytest", "pytest-cov", "flake8", "pdfminer", "tox"] + [[package]] category = "main" description = "Python versioning with requirements.txt syntax" @@ -799,11 +898,17 @@ six = "*" [[package]] category = "main" -description = "Julian dates from proleptic Gregorian and Julian calendars." -name = "jdcal" +description = "A Python utility / library to sort Python imports." +name = "isort" optional = false -python-versions = "*" -version = "1.4.1" +python-versions = ">=3.6.1,<4.0" +version = "5.9.1" + +[package.extras] +colors = ["colorama (>=0.4.3,<0.5.0)"] +pipfile_deprecated_finder = ["pipreqs", "requirementslib"] +plugins = ["setuptools"] +requirements_deprecated_finder = ["pipreqs", "pip-api"] [[package]] category = "main" @@ -853,6 +958,27 @@ optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" version = "0.10.0" +[[package]] +category = "main" +description = "JavaScript to Python Translator & JavaScript interpreter written in 100% pure Python." +name = "js2py" +optional = false +python-versions = "*" +version = "0.71" + +[package.dependencies] +pyjsparser = ">=2.5.1" +six = ">=1.10" +tzlocal = ">=1.2" + +[[package]] +category = "main" +description = "Library with helpers for the jsonlines file format" +name = "jsonlines" +optional = false +python-versions = ">=3.6" +version = "2.0.0" + [[package]] category = "main" description = "An implementation of JSON Schema validation for Python" @@ -930,6 +1056,14 @@ version = "0.0.5" delorean = ">=0.4.4" schema = ">=0.3.1,<0.4.0" +[[package]] +category = "main" +description = "A fast and thorough lazy object proxy." +name = "lazy-object-proxy" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +version = "1.6.0" + [[package]] category = "main" description = "Levenshtein edit distance library" @@ -1004,6 +1138,14 @@ numpy = ">=1.11" pyparsing = ">=2.0.1,<2.0.4 || >2.0.4,<2.1.2 || >2.1.2,<2.1.6 || >2.1.6" python-dateutil = ">=2.1" +[[package]] +category = "main" +description = "McCabe checker, plugin for flake8" +name = "mccabe" +optional = false +python-versions = "*" +version = "0.6.1" + [[package]] category = "main" description = "Rolling backport of unittest.mock for all Pythons" @@ -1020,14 +1162,6 @@ six = ">=1.9" docs = ["sphinx", "Pygments (<2)", "jinja2 (<2.7)", "sphinx (<1.3)"] test = ["unittest2 (>=1.1.0)"] -[[package]] -category = "main" -description = "An implementation of time.monotonic() for Python 2 & < 3.3" -name = "monotonic" -optional = false -python-versions = "*" -version = "1.5" - [[package]] category = "main" description = "D3 Viewer for Matplotlib" @@ -1053,6 +1187,14 @@ optional = false python-versions = ">=3.5" version = "4.7.6" +[[package]] +category = "main" +description = "Experimental type system extensions for programs checked with the mypy typechecker." +name = "mypy-extensions" +optional = false +python-versions = "*" +version = "0.4.3" + [[package]] category = "main" description = "Python interface to MySQL" @@ -1061,14 +1203,6 @@ optional = false python-versions = ">=3.5" version = "2.0.3" -[[package]] -category = "main" -description = "Simple natural order sorting API for Python" -name = "naturalsort" -optional = false -python-versions = "*" -version = "1.5.1" - [[package]] category = "main" description = "A network address manipulation library for Python" @@ -1106,8 +1240,8 @@ category = "main" description = "NumPy is the fundamental package for array computing with Python." name = "numpy" optional = false -python-versions = ">=3.6" -version = "1.19.5" +python-versions = ">=3.7" +version = "1.21.0" [[package]] category = "main" @@ -1161,11 +1295,10 @@ description = "A Python library to read/write Excel 2010 xlsx/xlsm files" name = "openpyxl" optional = false python-versions = ">=3.6," -version = "3.0.5" +version = "3.0.7" [package.dependencies] et-xmlfile = "*" -jdcal = "*" [[package]] category = "main" @@ -1316,6 +1449,14 @@ optional = false python-versions = "*" version = "1.6.5" +[[package]] +category = "main" +description = "Utility library for gitignore style pattern matching of file paths." +name = "pathspec" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "0.8.1" + [[package]] category = "main" description = "Python Build Reasonableness" @@ -1330,11 +1471,22 @@ description = "A wrapper around the pdftoppm and pdftocairo command line tools t name = "pdf2image" optional = false python-versions = "*" -version = "1.14.0" +version = "1.16.0" [package.dependencies] pillow = "*" +[[package]] +category = "main" +description = "PDF parser and analyzer" +name = "pdfminer" +optional = false +python-versions = ">=3.6" +version = "20191125" + +[package.dependencies] +pycryptodome = "*" + [[package]] category = "main" description = "Pexpect allows easy control of interactive console applications." @@ -1352,7 +1504,7 @@ description = "Python version of Google's common library for parsing, formatting name = "phonenumbers" optional = false python-versions = "*" -version = "8.12.15" +version = "8.12.26" [[package]] category = "main" @@ -1374,13 +1526,29 @@ version = "4.1.0" retrying = ">=1.3.3" six = "*" +[[package]] +category = "main" +description = "Python Lex & Yacc" +name = "ply" +optional = false +python-versions = "*" +version = "3.4" + +[[package]] +category = "main" +description = "A library to manipulate gettext files (po and mo files)." +name = "polib" +optional = false +python-versions = "*" +version = "1.1.0" + [[package]] category = "main" description = "Turns CSS blocks into style attributes" name = "premailer" optional = false python-versions = "*" -version = "3.7.0" +version = "3.9.0" [package.dependencies] cachetools = "*" @@ -1393,18 +1561,6 @@ requests = "*" dev = ["tox", "twine", "therapist", "black", "flake8", "wheel"] test = ["nose", "mock"] -[[package]] -category = "main" -description = "Useful property variants for Python programming (required properties, writable properties, cached properties, etc)" -name = "property-manager" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "3.0" - -[package.dependencies] -humanfriendly = ">=8.0" -verboselogs = ">=1.1" - [[package]] category = "main" description = "psutil is a cross-platform library for retrieving information onrunning processes and system utilization (CPU, memory, disks, network)in Python." @@ -1465,6 +1621,14 @@ lxml = "*" setuptools = "*" six = ">=1.9" +[[package]] +category = "main" +description = "Python style guide checker" +name = "pycodestyle" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.7.0" + [[package]] category = "main" description = "ISO country, subdivision, language, currency and script definitions and their translations" @@ -1481,6 +1645,14 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" version = "2.20" +[[package]] +category = "main" +description = "Cryptographic library for Python" +name = "pycryptodome" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "3.10.1" + [[package]] category = "main" description = "Python interface to Graphviz's Dot" @@ -1492,6 +1664,14 @@ version = "1.2.3" [package.dependencies] pyparsing = ">=2.1.4" +[[package]] +category = "main" +description = "passive checker of Python programs" +name = "pyflakes" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.3.1" + [[package]] category = "main" description = "Pygments is a syntax highlighting package written in Python." @@ -1522,6 +1702,14 @@ version = "0.7" [package.dependencies] setuptools = "*" +[[package]] +category = "main" +description = "Fast javascript parser (based on esprima.js)" +name = "pyjsparser" +optional = false +python-versions = "*" +version = "2.7.1" + [[package]] category = "main" description = "JSON Web Token implementation in Python" @@ -1546,13 +1734,64 @@ version = "2.4.28" [package.dependencies] setuptools = "*" +[[package]] +category = "main" +description = "python code static checker" +name = "pylint" +optional = false +python-versions = ">=3.5.*" +version = "2.6.0" + +[package.dependencies] +astroid = ">=2.4.0,<=2.5" +colorama = "*" +isort = ">=4.2.5,<6" +mccabe = ">=0.6,<0.7" +toml = ">=0.7.1" + +[[package]] +category = "main" +description = "Pylint plugin for Odoo" +name = "pylint-odoo" +optional = false +python-versions = ">=2.7" +version = "3.8.0" + +[package.dependencies] +Pygments = "2.6.1" +docutils = "0.16" +lxml = ">=4.2.3" +pbr = "*" +polib = "1.1.0" +pylint = "2.6.0" +pylint-plugin-utils = "0.6" +restructuredtext_lint = "1.3.1" +rfc3986 = "*" +six = "*" +whichcraft = "*" + +[package.source] +reference = "455ac91d2d6d651bf67ec8eae7dae516f11b1dec" +type = "git" +url = "https://github.com/oca/pylint-odoo.git" +[[package]] +category = "main" +description = "Utilities and helpers for writing Pylint plugins" +name = "pylint-plugin-utils" +optional = false +python-versions = "*" +version = "0.6" + +[package.dependencies] +pylint = ">=1.7" + [[package]] category = "main" description = "DB-API interface to Microsoft SQL Server for Python. (new Cython-based version)" name = "pymssql" optional = false python-versions = "*" -version = "2.1.5" +version = "2.2.1" [[package]] category = "main" @@ -1588,7 +1827,7 @@ description = "Python One Time Password Library" name = "pyotp" optional = false python-versions = "*" -version = "2.4.1" +version = "2.6.0" [[package]] category = "main" @@ -1619,29 +1858,12 @@ category = "main" description = "Python interface to PROJ (cartographic projections and coordinate transformations library)" name = "pyproj" optional = false -python-versions = ">=3.6" -version = "3.0.0.post1" +python-versions = ">=3.7" +version = "3.1.0" [package.dependencies] certifi = "*" -[[package]] -category = "main" -description = "A python implmementation of GNU readline." -marker = "sys_platform == \"win32\"" -name = "pyreadline" -optional = false -python-versions = "*" -version = "2.1" - -[[package]] -category = "main" -description = "Implementation of some RFC standard algorithms" -name = "pyrfc" -optional = false -python-versions = "*" -version = "0.1.2" - [[package]] category = "main" description = "Persistent/Functional/Immutable data structures" @@ -1771,8 +1993,8 @@ category = "main" description = "A Python Slugify application that handles Unicode" name = "python-slugify" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "4.0.1" +python-versions = ">=3.6" +version = "5.0.2" [package.dependencies] text-unidecode = ">=1.3" @@ -1786,7 +2008,7 @@ description = "Python module to handle standardized numbers and codes" name = "python-stdnum" optional = false python-versions = "*" -version = "1.15" +version = "1.16" [package.extras] soap = ["zeep"] @@ -1943,7 +2165,7 @@ description = "Mock out responses from the requests package" name = "requests-mock" optional = false python-versions = "*" -version = "1.8.0" +version = "1.9.3" [package.dependencies] requests = ">=2.3,<3" @@ -1979,6 +2201,17 @@ version = "0.9.1" [package.dependencies] requests = ">=2.0.1,<3.0.0" +[[package]] +category = "main" +description = "reStructuredText linter" +name = "restructuredtext-lint" +optional = false +python-versions = "*" +version = "1.3.1" + +[package.dependencies] +docutils = ">=0.11,<1.0" + [[package]] category = "main" description = "Retrying" @@ -2001,37 +2234,6 @@ version = "1.4.0" [package.extras] idna2008 = ["idna"] -[[package]] -category = "main" -description = "Simple command line interface for backup rotation" -name = "rotate-backups" -optional = false -python-versions = "*" -version = "4.3" - -[package.dependencies] -coloredlogs = ">=5.0" -executor = ">=13.0" -humanfriendly = ">=1.44.5" -naturalsort = ">=1.4" -property-manager = ">=2.0" -python-dateutil = ">=2.2" -simpleeval = ">=0.8.7" -six = ">=1.9.0" -verboselogs = ">=1.4" - -[[package]] -category = "main" -description = "Simple command line interface for S3 backup rotation" -name = "rotate-backups-s3" -optional = false -python-versions = "*" -version = "0.3" - -[package.dependencies] -boto = "*" -rotate-backups = "4.3" - [[package]] category = "main" description = "An Amazon S3 Transfer Manager" @@ -2085,14 +2287,6 @@ all = ["pytest", "pytest-cov", "numpy"] test = ["pytest", "pytest-cov"] vectorized = ["numpy"] -[[package]] -category = "main" -description = "A simple, safe single expression evaluator library." -name = "simpleeval" -optional = false -python-versions = "*" -version = "0.9.10" - [[package]] category = "main" description = "Simple, fast, extensible JSON encoder/decoder for Python" @@ -2109,6 +2303,17 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" version = "1.15.0" +[[package]] +category = "main" +description = "SlimIt - JavaScript minifier" +name = "slimit" +optional = false +python-versions = "*" +version = "0.8.1" + +[package.dependencies] +ply = ">=3.4" + [[package]] category = "main" description = "A generic slugifier." @@ -2148,6 +2353,7 @@ wstools = "*" [[package]] category = "main" description = "A modern CSS selector implementation for Beautiful Soup." +marker = "python_version >= \"3.0\"" name = "soupsieve" optional = false python-versions = "*" @@ -2158,8 +2364,8 @@ category = "main" description = "Python documentation generator" name = "sphinx" optional = false -python-versions = ">=3.5" -version = "3.4.3" +python-versions = ">=3.6" +version = "4.0.2" [package.dependencies] Jinja2 = ">=2.3" @@ -2167,7 +2373,7 @@ Pygments = ">=2.0" alabaster = ">=0.7,<0.8" babel = ">=1.3" colorama = ">=0.3.5" -docutils = ">=0.12" +docutils = ">=0.14,<0.18" imagesize = "*" packaging = "*" requests = ">=2.5.0" @@ -2182,7 +2388,7 @@ sphinxcontrib-serializinghtml = "*" [package.extras] docs = ["sphinxcontrib-websupport"] -lint = ["flake8 (>=3.5.0)", "isort", "mypy (>=0.790)", "docutils-stubs"] +lint = ["flake8 (>=3.5.0)", "isort", "mypy (>=0.800)", "docutils-stubs"] test = ["pytest", "pytest-cov", "html5lib", "cython", "typed-ast"] [[package]] @@ -2221,9 +2427,10 @@ description = "Read the Docs theme for Sphinx" name = "sphinx-rtd-theme" optional = false python-versions = "*" -version = "0.5.1" +version = "0.5.2" [package.dependencies] +docutils = "<0.17" sphinx = "*" [package.extras] @@ -2305,20 +2512,37 @@ category = "main" description = "Database Abstraction Library" name = "sqlalchemy" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.3.22" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +version = "1.4.19" + +[package.dependencies] +[package.dependencies.greenlet] +python = ">=3" +version = "!=0.4.17" + +[package.dependencies.importlib-metadata] +python = "<3.8" +version = "*" [package.extras] +aiomysql = ["greenlet (!=0.4.17)", "aiomysql"] +aiosqlite = ["greenlet (!=0.4.17)", "aiosqlite"] +asyncio = ["greenlet (!=0.4.17)"] +mariadb_connector = ["mariadb (>=1.0.1)"] mssql = ["pyodbc"] mssql_pymssql = ["pymssql"] mssql_pyodbc = ["pyodbc"] -mysql = ["mysqlclient"] -oracle = ["cx-oracle"] -postgresql = ["psycopg2"] -postgresql_pg8000 = ["pg8000"] +mypy = ["sqlalchemy2-stubs", "mypy (>=0.800)"] +mysql = ["mysqlclient (>=1.4.0,<2)", "mysqlclient (>=1.4.0)"] +mysql_connector = ["mysqlconnector"] +oracle = ["cx_oracle (>=7,<8)", "cx_oracle (>=7)"] +postgresql = ["psycopg2 (>=2.7)"] +postgresql_asyncpg = ["greenlet (!=0.4.17)", "asyncpg"] +postgresql_pg8000 = ["pg8000 (>=1.16.6)"] postgresql_psycopg2binary = ["psycopg2-binary"] postgresql_psycopg2cffi = ["psycopg2cffi"] -pymysql = ["pymysql"] +pymysql = ["pymysql (<1)", "pymysql"] +sqlcipher = ["sqlcipher3-binary"] [[package]] category = "main" @@ -2359,6 +2583,21 @@ optional = false python-versions = "*" version = "1.3" +[[package]] +category = "main" +description = "tinycss2" +name = "tinycss2" +optional = false +python-versions = ">=3.6" +version = "1.1.0" + +[package.dependencies] +webencodings = ">=0.4" + +[package.extras] +doc = ["sphinx", "sphinx-rtd-theme"] +test = ["pytest", "pytest-cov", "pytest-flake8", "pytest-isort", "coverage"] + [[package]] category = "main" description = "Python Library for Tom's Obvious, Minimal Language" @@ -2395,10 +2634,19 @@ version = "3.8.2" requests = ">=2.1.0" requests-oauthlib = ">=0.4.0" +[[package]] +category = "main" +description = "a fork of Python 2 and 3 ast modules with type comment support" +marker = "implementation_name == \"cpython\" and python_version < \"3.8\" or python_version < \"3.8\"" +name = "typed-ast" +optional = false +python-versions = "*" +version = "1.4.3" + [[package]] category = "main" description = "Backported and Experimental Type Hints for Python 3.5+" -marker = "python_version >= \"3.6\" and python_version < \"3.8\"" +marker = "python_version >= \"3.6\" and python_version < \"3.8\" or python_version < \"3.8\"" name = "typing-extensions" optional = false python-versions = "*" @@ -2485,14 +2733,6 @@ version = "0.1.7" [package.dependencies] vcrpy = "*" -[[package]] -category = "main" -description = "Verbose logging level for Python's logging module" -name = "verboselogs" -optional = false -python-versions = "*" -version = "1.7" - [[package]] category = "main" description = "Create standard barcodes with Python. No external modules needed (optional PIL support included)." @@ -2536,14 +2776,19 @@ six = "*" [[package]] category = "main" -description = "WebSocket client for Python. hybi13 is supported." +description = "Character encoding aliases for legacy web content" +name = "webencodings" +optional = false +python-versions = "*" +version = "0.5.1" + +[[package]] +category = "main" +description = "WebSocket client for Python with low level API options" name = "websocket-client" optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "0.57.0" - -[package.dependencies] -six = "*" +python-versions = ">=3.6" +version = "1.1.0" [[package]] category = "main" @@ -2551,7 +2796,7 @@ description = "WeChat SDK for Python" name = "wechatpy" optional = false python-versions = "*" -version = "1.8.14" +version = "1.8.15" [package.dependencies] optionaldict = ">=0.1.0" @@ -2572,6 +2817,14 @@ optional = false python-versions = "*" version = "0.11.15" +[[package]] +category = "main" +description = "pure python download utility" +name = "wget" +optional = false +python-versions = "*" +version = "3.2" + [[package]] category = "main" description = "A built-package format for Python" @@ -2583,6 +2836,14 @@ version = "0.36.2" [package.extras] test = ["pytest (>=3.0.0)", "pytest-cov"] +[[package]] +category = "main" +description = "This package provides cross-platform cross-python shutil.which functionality." +name = "whichcraft" +optional = false +python-versions = "*" +version = "0.6.1" + [[package]] category = "main" description = "Module for decorators, wrappers and monkey patching." @@ -2628,6 +2889,14 @@ optional = false python-versions = "*" version = "1.3.0" +[[package]] +category = "main" +description = "Format and compress XML documents" +name = "xmlformatter" +optional = false +python-versions = "*" +version = "0.2.2" + [[package]] category = "main" description = "Makes working with XML feel like you are working with JSON" @@ -2701,7 +2970,7 @@ python-versions = "*" version = "4.4.28" [metadata] -content-hash = "88ae1fc45a0fb59a5ede3d1a1e0220c8f5cde8722a7bf01435a65298eaa66599" +content-hash = "8f717dd4d3138e704720a02bc6ca7efb301108825e0cfc0dcd16c2a8d3822b6c" lock-version = "1.0" python-versions = "^3.7.7" @@ -2723,8 +2992,8 @@ appdirs = [ {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, ] argcomplete = [ - {file = "argcomplete-1.12.2-py2.py3-none-any.whl", hash = "sha256:17f01a9b9b9ece3e6b07058eae737ad6e10de8b4e149105f84614783913aba71"}, - {file = "argcomplete-1.12.2.tar.gz", hash = "sha256:de0e1282330940d52ea92a80fea2e4b9e0da1932aaa570f84d268939d1897b04"}, + {file = "argcomplete-1.12.3-py2.py3-none-any.whl", hash = "sha256:291f0beca7fd49ce285d2f10e4c1c77e9460cf823eef2de54df0c0fec88b0d81"}, + {file = "argcomplete-1.12.3.tar.gz", hash = "sha256:2c7dbffd8c045ea534921e63b0be6fe65e88599990d8dc408ac8c542b72a5445"}, ] argparse = [ {file = "argparse-1.4.0-py2.py3-none-any.whl", hash = "sha256:c31647edb69fd3d465a847ea3157d37bed1f95f19760b11a47aa91c04b666314"}, @@ -2737,6 +3006,10 @@ asn1crypto = [ asterisk = [ {file = "asterisk-0.0.8.tar.gz", hash = "sha256:a7813896f355f8ed0ca1bdea05938a10c2788255332fc826cf87a4cb34308f37"}, ] +astroid = [ + {file = "astroid-2.5-py3-none-any.whl", hash = "sha256:87ae7f2398b8a0ae5638ddecf9987f081b756e0e9fc071aeebdca525671fc4dc"}, + {file = "astroid-2.5.tar.gz", hash = "sha256:b31c92f545517dcc452f284bc9c044050862fbe6d93d2b3de4a215a6b384bf0d"}, +] attrs = [ {file = "attrs-19.3.0-py2.py3-none-any.whl", hash = "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c"}, {file = "attrs-19.3.0.tar.gz", hash = "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"}, @@ -2767,35 +3040,32 @@ bcrypt = [ {file = "bcrypt-3.1.7.tar.gz", hash = "sha256:0b0069c752ec14172c5f78208f1863d7ad6755a6fae6fe76ec2c80d13be41e42"}, ] beautifulsoup4 = [ - {file = "beautifulsoup4-4.9.1-py2-none-any.whl", hash = "sha256:e718f2342e2e099b640a34ab782407b7b676f47ee272d6739e60b8ea23829f2c"}, - {file = "beautifulsoup4-4.9.1-py3-none-any.whl", hash = "sha256:a6237df3c32ccfaee4fd201c8f5f9d9df619b93121d01353a64a73ce8c6ef9a8"}, - {file = "beautifulsoup4-4.9.1.tar.gz", hash = "sha256:73cc4d115b96f79c7d77c1c7f7a0a8d4c57860d1041df407dd1aae7f07a77fd7"}, + {file = "beautifulsoup4-4.9.3-py2-none-any.whl", hash = "sha256:4c98143716ef1cb40bf7f39a8e3eec8f8b009509e74904ba3a7b315431577e35"}, + {file = "beautifulsoup4-4.9.3-py3-none-any.whl", hash = "sha256:fff47e031e34ec82bf17e00da8f592fe7de69aeea38be00523c04623c04fb666"}, + {file = "beautifulsoup4-4.9.3.tar.gz", hash = "sha256:84729e322ad1d5b4d25f805bfa05b902dd96450f43842c4e99067d5e1369eb25"}, ] +black = [] bokeh = [ {file = "bokeh-1.1.0.tar.gz", hash = "sha256:70c944ccb99faea9c1bc2b77caba4dbcd884e083fc32511efbd6f895d7cb6832"}, ] -boto = [ - {file = "boto-2.49.0-py2.py3-none-any.whl", hash = "sha256:147758d41ae7240dc989f0039f27da8ca0d53734be0eb869ef16e3adcfa462e8"}, - {file = "boto-2.49.0.tar.gz", hash = "sha256:ea0d3b40a2d852767be77ca343b58a9e3a4b00d9db440efb8da74b4e58025e5a"}, -] boto3 = [ {file = "boto3-1.9.102-py2.py3-none-any.whl", hash = "sha256:4605a0707e857f316a7b01766fb49350e7b3d922458aa9c870f6393ec6fa22ca"}, {file = "boto3-1.9.102.tar.gz", hash = "sha256:1f43d7a4865b75c4628a5084c2c32b00f356a9fd09f97574a8903c574356890a"}, ] botocore = [ - {file = "botocore-1.12.253-py2.py3-none-any.whl", hash = "sha256:dc080aed4f9b220a9e916ca29ca97a9d37e8e1d296fe89cbaeef929bf0c8066b"}, - {file = "botocore-1.12.253.tar.gz", hash = "sha256:3baf129118575602ada9926f5166d82d02273c250d0feb313fc270944b27c48b"}, + {file = "botocore-1.12.191-py2.py3-none-any.whl", hash = "sha256:6f609214e358d602a927af375e851af8edff0fb7dcdc0f9790416936eded0442"}, + {file = "botocore-1.12.191.tar.gz", hash = "sha256:971bfcce68b0c92cb8ff6c43a080a2baa07f0f6809582d758da19c14fc039da0"}, ] cached-property = [ {file = "cached-property-1.5.1.tar.gz", hash = "sha256:9217a59f14a5682da7c4b8829deadbfc194ac22e9908ccf7c8820234e80a1504"}, {file = "cached_property-1.5.1-py2.py3-none-any.whl", hash = "sha256:3a026f1a54135677e7da5ce819b0c690f156f37976f3e30c5430740725203d7f"}, ] cachetools = [ - {file = "cachetools-4.2.0-py3-none-any.whl", hash = "sha256:c6b07a6ded8c78bf36730b3dc452dfff7d95f2a12a2fed856b1a0cb13ca78c61"}, - {file = "cachetools-4.2.0.tar.gz", hash = "sha256:3796e1de094f0eaca982441c92ce96c68c89cced4cd97721ab297ea4b16db90e"}, + {file = "cachetools-4.2.2-py3-none-any.whl", hash = "sha256:2cc0b89715337ab6dbba85b5b50effe2b0c74e035d83ee8ed637cf52f12ae001"}, + {file = "cachetools-4.2.2.tar.gz", hash = "sha256:61b5ed1e22a0924aed1d23b478f37e8d52549ff8a961de2909c69bf950020cff"}, ] cerberus = [ - {file = "Cerberus-1.3.2.tar.gz", hash = "sha256:302e6694f206dd85cb63f13fd5025b31ab6d38c99c50c6d769f8fa0b0f299589"}, + {file = "Cerberus-1.3.4.tar.gz", hash = "sha256:d1b21b3954b2498d9a79edf16b3170a3ac1021df88d197dc2ce5928ba519237c"}, ] certifi = [ {file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"}, @@ -2836,8 +3106,11 @@ chardet = [ {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, ] click = [ - {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"}, - {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"}, + {file = "click-8.0.1-py3-none-any.whl", hash = "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"}, + {file = "click-8.0.1.tar.gz", hash = "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a"}, +] +cloudflare = [ + {file = "cloudflare-2.8.15.tar.gz", hash = "sha256:1f47bd324f80e91487dea2c79be934b1dc612bcfa63e784dcf74c6a2f52a41cc"}, ] code-writer = [ {file = "code-writer-1.1.1.tar.gz", hash = "sha256:485260d0444707876596c499bd9b1ef9a11dc720d741ac57c884216de9fa3f40"}, @@ -2847,10 +3120,6 @@ colorama = [ {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, ] -coloredlogs = [ - {file = "coloredlogs-14.0-py2.py3-none-any.whl", hash = "sha256:346f58aad6afd48444c2468618623638dadab76e4e70d5e10822676f2d32226a"}, - {file = "coloredlogs-14.0.tar.gz", hash = "sha256:a1fab193d2053aa6c0a97608c4342d031f1f93a3d1218432c59322441d31a505"}, -] compressed-rtf = [ {file = "compressed_rtf-1.0.6.tar.gz", hash = "sha256:c1c827f1d124d24608981a56e8b8691eb1f2a69a78ccad6440e7d92fde1781dd"}, ] @@ -2875,6 +3144,11 @@ cryptography = [ {file = "cryptography-2.6.1-cp37-cp37m-win_amd64.whl", hash = "sha256:2afb83308dc5c5255149ff7d3fb9964f7c9ee3d59b603ec18ccf5b0a8852e2b1"}, {file = "cryptography-2.6.1.tar.gz", hash = "sha256:26c821cbeb683facb966045e2064303029d572a87ee69ca5a1bf54bf55f93ca6"}, ] +css-html-prettify = [ + {file = "css-html-prettify-2.5.5.zip", hash = "sha256:4fbdd6d42256fc9573fea57874852b8df58bef469b0a3e2f154000b85bcbbc44"}, + {file = "css_html_prettify-2.5.5-py2.py3-none-any.whl", hash = "sha256:992040e47cd81511c8ca8f632febda380b7d93908418703a29d310c0b56077a6"}, + {file = "css_html_prettify-2.5.5-py3.6.egg", hash = "sha256:d1df7cf0830298a5dd532dfefa240291021d66097b4f8446cbbf3b3050f04b61"}, +] cssselect = [ {file = "cssselect-1.1.0-py2.py3-none-any.whl", hash = "sha256:f612ee47b749c877ebae5bb77035d8f4202c6ad0f0fc1271b3c18ad6c4468ecf"}, {file = "cssselect-1.1.0.tar.gz", hash = "sha256:f95f8dedd925fd8f54edb3d2dfb44c190d9d18512377d3c1e2388d16126879bc"}, @@ -2888,41 +3162,41 @@ cycler = [ {file = "cycler-0.10.0.tar.gz", hash = "sha256:cd7b2d1018258d7247a71425e9f26463dfb444d411c39569972f4ce586b0c9d8"}, ] cython = [ - {file = "Cython-0.29.21-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:c541b2b49c6638f2b5beb9316726db84a8d1c132bf31b942dae1f9c7f6ad3b92"}, - {file = "Cython-0.29.21-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:b8d8497091c1dc8705d1575c71e908a93b1f127a174b2d472020f3d84263ac28"}, - {file = "Cython-0.29.21-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:695a6bcaf9e12b1e471dfce96bbecf22a1487adc2ac6106b15960a2b51b97f5d"}, - {file = "Cython-0.29.21-cp27-cp27m-win32.whl", hash = "sha256:171b9f70ceafcec5852089d0f9c1e75b0d554f46c882cd4e2e4acaba9bd7d148"}, - {file = "Cython-0.29.21-cp27-cp27m-win_amd64.whl", hash = "sha256:539e59949aab4955c143a468810123bf22d3e8556421e1ce2531ed4893914ca0"}, - {file = "Cython-0.29.21-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:e93acd1f603a0c1786e0841f066ae7cef014cf4750e3cd06fd03cfdf46361419"}, - {file = "Cython-0.29.21-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:2922e3031ba9ebbe7cb9200b585cc33b71d66023d78450dcb883f824f4969371"}, - {file = "Cython-0.29.21-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:497841897942f734b0abc2dead2d4009795ee992267a70a23485fd0e937edc0b"}, - {file = "Cython-0.29.21-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:0ac10bf476476a9f7ef61ec6e44c280ef434473124ad31d3132b720f7b0e8d2a"}, - {file = "Cython-0.29.21-cp34-cp34m-win32.whl", hash = "sha256:31c71a615f38401b0dc1f2a5a9a6c421ffd8908c4cd5bbedc4014c1b876488e8"}, - {file = "Cython-0.29.21-cp34-cp34m-win_amd64.whl", hash = "sha256:c4b78356074fcaac04ecb4de289f11d506e438859877670992ece11f9c90f37b"}, - {file = "Cython-0.29.21-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:b2f9172e4d6358f33ecce6a4339b5960f9f83eab67ea244baa812737793826b7"}, - {file = "Cython-0.29.21-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:856c7fb31d247ce713d60116375e1f8153d0291ab5e92cca7d8833a524ba9991"}, - {file = "Cython-0.29.21-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:715294cd2246b39a8edca464a8366eb635f17213e4a6b9e74e52d8b877a8cb63"}, - {file = "Cython-0.29.21-cp35-cp35m-win32.whl", hash = "sha256:23f3a00b843a19de8bb4468b087db5b413a903213f67188729782488d67040e0"}, - {file = "Cython-0.29.21-cp35-cp35m-win_amd64.whl", hash = "sha256:ccb77faeaad99e99c6c444d04862c6cf604204fe0a07d4c8f9cbf2c9012d7d5a"}, - {file = "Cython-0.29.21-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e272ed97d20b026f4f25a012b25d7d7672a60e4f72b9ca385239d693cd91b2d5"}, - {file = "Cython-0.29.21-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:8c6e25e9cc4961bb2abb1777c6fa9d0fa2d9b014beb3276cebe69996ff162b78"}, - {file = "Cython-0.29.21-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:57ead89128dee9609119c93d3926c7a2add451453063147900408a50144598c6"}, - {file = "Cython-0.29.21-cp36-cp36m-win32.whl", hash = "sha256:0e25c209c75df8785480dcef85db3d36c165dbc0f4c503168e8763eb735704f2"}, - {file = "Cython-0.29.21-cp36-cp36m-win_amd64.whl", hash = "sha256:a0674f246ad5e1571ef29d4c5ec1d6ecabe9e6c424ad0d6fee46b914d5d24d69"}, - {file = "Cython-0.29.21-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5da187bebe38030325e1c0b5b8a804d489410be2d384c0ef3ba39493c67eb51e"}, - {file = "Cython-0.29.21-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:9ce5e5209f8406ffc2b058b1293cce7a954911bb7991e623564d489197c9ba30"}, - {file = "Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5e545a48f919e40079b0efe7b0e081c74b96f9ef25b9c1ff4cdbd95764426b58"}, - {file = "Cython-0.29.21-cp37-cp37m-win32.whl", hash = "sha256:c8435959321cf8aec867bbad54b83b7fb8343204b530d85d9ea7a1f5329d5ac2"}, - {file = "Cython-0.29.21-cp37-cp37m-win_amd64.whl", hash = "sha256:540b3bee0711aac2e99bda4fa0a46dbcd8c74941666bfc1ef9236b1a64eeffd9"}, - {file = "Cython-0.29.21-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:93f5fed1c9445fb7afe20450cdaf94b0e0356d47cc75008105be89c6a2e417b1"}, - {file = "Cython-0.29.21-cp38-cp38-manylinux1_i686.whl", hash = "sha256:9207fdedc7e789a3dcaca628176b80c82fbed9ae0997210738cbb12536a56699"}, - {file = "Cython-0.29.21-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:603b9f1b8e93e8b494d3e89320c410679e21018e48b6cbc77280f5db71f17dc0"}, - {file = "Cython-0.29.21-cp38-cp38-win32.whl", hash = "sha256:473df5d5e400444a36ed81c6596f56a5b52a3481312d0a48d68b777790f730ae"}, - {file = "Cython-0.29.21-cp38-cp38-win_amd64.whl", hash = "sha256:b8a8a31b9e8860634adbca30fea1d0c7f08e208b3d7611f3e580e5f20992e5d7"}, - {file = "Cython-0.29.21-cp39-cp39-manylinux1_i686.whl", hash = "sha256:7ebaa8800c376bcdae596fb1372cb4232a5ef957619d35839520d2786f2debb9"}, - {file = "Cython-0.29.21-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:c111ac9abdf715762e4fb87395e59d61c0fbb6ce79eb2e24167700b6cfa8ba79"}, - {file = "Cython-0.29.21-py2.py3-none-any.whl", hash = "sha256:5c4276fdcbccdf1e3c1756c7aeb8395e9a36874fa4d30860e7694f43d325ae13"}, - {file = "Cython-0.29.21.tar.gz", hash = "sha256:e57acb89bd55943c8d8bf813763d20b9099cc7165c0f16b707631a7654be9cad"}, + {file = "Cython-0.29.23-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ff885f18d169759b57f116d3956e45cd2b9cba989fde348bba091544c668dc11"}, + {file = "Cython-0.29.23-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:3b29224eb62309a10819d923dc6262f769e4f3facfee3cd06372c355e5b38b33"}, + {file = "Cython-0.29.23-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:355a6e768d91e21fbf477b61881bab64b7a2da386a166898997bccefd532cf5d"}, + {file = "Cython-0.29.23-cp27-cp27m-win32.whl", hash = "sha256:2af52d312e96b38ded38b34d06e22685c226b1b0e58278bd27209f5d2385d115"}, + {file = "Cython-0.29.23-cp27-cp27m-win_amd64.whl", hash = "sha256:519fccf526d26b377e1db22f22aa44889b28bc5833ec106588cb13557e8ba2da"}, + {file = "Cython-0.29.23-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:625a16103770fd92b487b701fb0c07e5790b080f40fa11ce572a2d56d9e9fcca"}, + {file = "Cython-0.29.23-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:7b7a766726d207d7cd57aff0fcb4b35ce042d3cc88a421fcdb45eeb61a5b9d12"}, + {file = "Cython-0.29.23-cp34-cp34m-win32.whl", hash = "sha256:474c1a29ab43e29d990df279e2cf6aa96baa9208f5cd4bc76ac87ffcdf1e2945"}, + {file = "Cython-0.29.23-cp34-cp34m-win_amd64.whl", hash = "sha256:f4aca6bffb1c1c3c4ada3347d0b162a699c18a66e097ee08b63b3a35118fdfcc"}, + {file = "Cython-0.29.23-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:58dc06871bfdb0592542d779714fe9f918e11ba20ac07757dd63b198bdc704fe"}, + {file = "Cython-0.29.23-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:2a3bbce689a2fddb85aa66712d93875c99bf7f64ac82b1d149ecce522a7a4e0c"}, + {file = "Cython-0.29.23-cp35-cp35m-win32.whl", hash = "sha256:3ef530f975e3a760e7282fce2a25f900fa63f96d17321b4aa5f5542eb9859cdf"}, + {file = "Cython-0.29.23-cp35-cp35m-win_amd64.whl", hash = "sha256:ef21c51350462160456eb71df31b0869e5141e940f22c61c358bdb6e3ebc3388"}, + {file = "Cython-0.29.23-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:20402ef316393168909926ab21848aa6e08e39bed5003b657139774e66166cd0"}, + {file = "Cython-0.29.23-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:4858043ac5f96a8f0277cf63760bb39b9521c1f897678cf1d22423f3e758f4ed"}, + {file = "Cython-0.29.23-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4d7c3b0882d8757c601eaf288fc0d321d5c7ac6c3afb8c42eddf9325a3419cf5"}, + {file = "Cython-0.29.23-cp36-cp36m-win32.whl", hash = "sha256:37ff66039e3d138ec968ee1d1e12441fa5fb4e6a9c5458bc3c3a232f01be4a7d"}, + {file = "Cython-0.29.23-cp36-cp36m-win_amd64.whl", hash = "sha256:5be3ae3189cf7d0e9bbeafb854496dc7030c6f6a5602d809435fab8223543a41"}, + {file = "Cython-0.29.23-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b0699f0dc90181f2458fdb8170455e7798a309e18f41379eda7a2dc8c7aadee0"}, + {file = "Cython-0.29.23-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:41cd0dd2ff5d78466e73409db509887a84449b400074d4f217980cedbb18e4be"}, + {file = "Cython-0.29.23-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:aa3bb0928fb2aa3a8828801eb8b29af2261c199f805ae835467489e2bdd00372"}, + {file = "Cython-0.29.23-cp37-cp37m-win32.whl", hash = "sha256:20cb50d9fede8029bdb50875458f07a27f909289aeed4cdb9c19544dd9a9bc45"}, + {file = "Cython-0.29.23-cp37-cp37m-win_amd64.whl", hash = "sha256:c4b82461edbbcf90f19b319006345b77474a2d7514e1476d49a14bbd55d6b797"}, + {file = "Cython-0.29.23-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:794e3df0b57e16bce7583ac909126f4cb381fe566adadb20484d89095855eedb"}, + {file = "Cython-0.29.23-cp38-cp38-manylinux1_i686.whl", hash = "sha256:0c4b9f7e3aa004cf3f364e3e772f55fec5740485bafea99d1f13bdc9bbd8a545"}, + {file = "Cython-0.29.23-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:ceccc03b633113ede1f14ad914a6db5c278ce108c8ddb308a5c01c1567d8a02a"}, + {file = "Cython-0.29.23-cp38-cp38-win32.whl", hash = "sha256:4b0bcf2e06a9063fc78c3243ed4003228375d532ef13b9e5d7183be8f0a52cf5"}, + {file = "Cython-0.29.23-cp38-cp38-win_amd64.whl", hash = "sha256:5a6792153b728a0240e55bbb5b643f4f7e45c76319e03abf15bf367471ea1d1a"}, + {file = "Cython-0.29.23-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a8eed9c82e8fe07b8a8ffbd36018871a17458903fc25c9d015f37b54513a3efd"}, + {file = "Cython-0.29.23-cp39-cp39-manylinux1_i686.whl", hash = "sha256:266459c7e48fe3c6c492b297e4033e42d4c6863cc1a1ff7cc4034949fc574fa6"}, + {file = "Cython-0.29.23-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:4b6824b58d4373224fc76ee8bee6b35c2d17c91a1ed0fa67b88440f63daebe50"}, + {file = "Cython-0.29.23-cp39-cp39-win32.whl", hash = "sha256:7d6a33c8a11f05f698e215bfdb837f32c27f63c20f3af863557ed91c748dc2be"}, + {file = "Cython-0.29.23-cp39-cp39-win_amd64.whl", hash = "sha256:2365f3b5e6451b6bc6dcd262230656f4ade1d862ec2f6c22154deebef37c08b6"}, + {file = "Cython-0.29.23-py2.py3-none-any.whl", hash = "sha256:282263628c5d601b313d5920f7b6d7e08c7fedbddacd080c4858aa04d86b6b4b"}, + {file = "Cython-0.29.23.tar.gz", hash = "sha256:6a0d31452f0245daacb14c979c77e093eb1a546c760816b5eed0047686baad8e"}, ] dateparser = [ {file = "dateparser-0.7.6-py2.py3-none-any.whl", hash = "sha256:7552c994f893b5cb8fcf103b4cd2ff7f57aab9bfd2619fdf0cf571c0740fd90b"}, @@ -2955,16 +3229,23 @@ dnspython = [ {file = "dnspython-2.0.0.zip", hash = "sha256:044af09374469c3a39eeea1a146e8cac27daec951f1f1f157b1962fc7cb9d1b7"}, ] docutils = [ - {file = "docutils-0.12-py3-none-any.whl", hash = "sha256:dcebd4928112631626f4c4d0df59787c748404e66dda952110030ea883d3b8cd"}, - {file = "docutils-0.12.tar.gz", hash = "sha256:c7db717810ab6965f66c8cf0398a98c9d8df982da39b4cd7f162911eb89596fa"}, + {file = "docutils-0.16-py2.py3-none-any.whl", hash = "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af"}, + {file = "docutils-0.16.tar.gz", hash = "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc"}, ] ebaysdk = [ {file = "ebaysdk-2.1.5-py3.7.egg", hash = "sha256:55360edc239037c3a0aaaf3f39889ddea666b8b1d97c893b2c3fd2269d868b45"}, {file = "ebaysdk-2.1.5.tar.gz", hash = "sha256:78458e1ea4a0fc7d693c26de363069696393767e4aa9689fd38efbfb08409acd"}, ] +ebcdic = [ + {file = "ebcdic-1.1.1-py2.py3-none-any.whl", hash = "sha256:33b4cb729bc2d0bf46cc1847b0e5946897cb8d3f53520c5b9aa5fa98d7e735f1"}, +] email-validator = [ - {file = "email-validator-1.1.2.tar.gz", hash = "sha256:1a13bd6050d1db4475f13e444e169b6fe872434922d38968c67cea9568cce2f0"}, - {file = "email_validator-1.1.2-py2.py3-none-any.whl", hash = "sha256:094b1d1c60d790649989d38d34f69e1ef07792366277a2cf88684d03495d018f"}, + {file = "email_validator-1.1.3-py2.py3-none-any.whl", hash = "sha256:5675c8ceb7106a37e40e2698a57c056756bf3f272cfa8682a4f87ebd95d8440b"}, + {file = "email_validator-1.1.3.tar.gz", hash = "sha256:aa237a65f6f4da067119b7df3f13e89c25c051327b2b5b66dc075f33d62480d7"}, +] +emoji = [ + {file = "emoji-1.2.0-py3-none-any.whl", hash = "sha256:6b19b65da8d6f30551eead1705539cc0eadcd9e33a6ecbc421a29b87f96287eb"}, + {file = "emoji-1.2.0.tar.gz", hash = "sha256:496f432058567985838c13d67dde84ca081614a8286c0b9cdc7d63dfa89d51a3"}, ] entrypoints = [ {file = "entrypoints-0.3-py2.py3-none-any.whl", hash = "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19"}, @@ -2976,31 +3257,28 @@ enum34 = [ {file = "enum34-1.1.10.tar.gz", hash = "sha256:cce6a7477ed816bd2542d03d53db9f0db935dd013b70f336a95c73979289f248"}, ] escpos = [ - {file = "escpos-1.8.tar.gz", hash = "sha256:54760134065b99c2ce9fd7fc3da1b5cff04580791e8a1849e56c3671b2d391be"}, + {file = "escpos-1.9-py3.8.egg", hash = "sha256:df5f7bad9ab904a3a41f3456e0bbecc436951ecce9c34825b7173507efa7c08e"}, + {file = "escpos-1.9.tar.gz", hash = "sha256:5acc126fa5ddd6ec395ccd9c7729545e91d85ebb2f5b17e9ab88e33d6925f501"}, ] et-xmlfile = [ {file = "et_xmlfile-1.0.1.tar.gz", hash = "sha256:614d9722d572f6246302c4491846d2c393c199cfa4edc9af593437691683335b"}, ] -executor = [ - {file = "executor-23.1-py2.py3-none-any.whl", hash = "sha256:0104bb9d7f5a3bd00642ad031ad2241d0663988bcb3da1c976e763db29b0d6ae"}, - {file = "executor-23.1.tar.gz", hash = "sha256:c8d4bba81d80c16612fcbcefd45439f45f82daa1d6e24c44b1832f3bb4649d5f"}, -] extract-msg = [ - {file = "extract_msg-0.28.0-py2.py3-none-any.whl", hash = "sha256:694ea75633e88d942b29a47c10dc9b6b9f84a2c42ebcf3d0c4b8ee0aed72755e"}, - {file = "extract_msg-0.28.0.tar.gz", hash = "sha256:72eace1f0c2dd772f3fd6745f736d5681eb7ee3e9d8102a56520bb2d6e9d3bfb"}, + {file = "extract_msg-0.28.7-py2.py3-none-any.whl", hash = "sha256:6ad2702bef86e6c1b8505e2993c7f3d37a1f3d140903138ee2df4a299dd2a29c"}, + {file = "extract_msg-0.28.7.tar.gz", hash = "sha256:7ebdbd7863a3699080a69f71ec0cd30ed9bfee70bad9acc6a8e6abe9523c78c0"}, ] factur-x = [ - {file = "factur-x-1.12.tar.gz", hash = "sha256:423d29ab0f8816cdb93bab9ebef4b6d7841c7b2ee747397d5b009ef5afce44e3"}, -] -fasteners = [ - {file = "fasteners-0.15-py2.py3-none-any.whl", hash = "sha256:007e4d2b2d4a10093f67e932e5166722d2eab83b77724156e92ad013c6226574"}, - {file = "fasteners-0.15.tar.gz", hash = "sha256:3a176da6b70df9bb88498e1a18a9e4a8579ed5b9141207762368a1017bf8f5ef"}, + {file = "factur-x-2.3.tar.gz", hash = "sha256:1b930a09ae6df3c9ed7bdf5d7088e7160304310840a7f29847c4e7296d5b1f0e"}, ] feedparser = [ {file = "feedparser-5.2.1.tar.bz2", hash = "sha256:ce875495c90ebd74b179855449040003a1beb40cd13d5f037a0654251e260b02"}, {file = "feedparser-5.2.1.tar.gz", hash = "sha256:bd030652c2d08532c034c27fcd7c85868e7fa3cb2b17f230a44a6bbc92519bf9"}, {file = "feedparser-5.2.1.zip", hash = "sha256:cd2485472e41471632ed3029d44033ee420ad0b57111db95c240c9160a85831c"}, ] +flake8 = [ + {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"}, + {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"}, +] freezegun = [ {file = "freezegun-0.3.11-py2.py3-none-any.whl", hash = "sha256:6cb82b276f83f2acce67f121dc2656f4df26c71e32238334eb071170b892a278"}, {file = "freezegun-0.3.11.tar.gz", hash = "sha256:e839b43bfbe8158b4d62bb97e6313d39f3586daf48e1314fb1083d2ef17700da"}, @@ -3075,9 +3353,12 @@ greenlet = [ html2text = [ {file = "html2text-2016.9.19.tar.gz", hash = "sha256:554ef5fd6c6cf6e3e4f725a62a3e9ec86a0e4d33cd0928136d1c79dbeb7b2d55"}, ] -humanfriendly = [ - {file = "humanfriendly-8.2-py2.py3-none-any.whl", hash = "sha256:e78960b31198511f45fd455534ae7645a6207d33e512d2e842c766d15d9c8080"}, - {file = "humanfriendly-8.2.tar.gz", hash = "sha256:bf52ec91244819c780341a3438d5d7b09f431d3f113a475147ac9b7b167a3d12"}, +html5lib = [ + {file = "html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d"}, + {file = "html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f"}, +] +html5print = [ + {file = "html5print-0.1.2.tar.gz", hash = "sha256:1ff645698a7192a61f8a5963f23dc894d16fa3346804a2d1ac462683f6e44d4b"}, ] humanize = [ {file = "humanize-2.5.0-py3-none-any.whl", hash = "sha256:89062c6db8601693b7d223443d0d7529aa9577df43a1387ddd4b9c273abb4a51"}, @@ -3100,8 +3381,8 @@ importlib-metadata = [ {file = "importlib_metadata-1.7.0.tar.gz", hash = "sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83"}, ] invoice2data = [ - {file = "invoice2data-0.3.5-py3.6.egg", hash = "sha256:5668b09cc6bcbc1c9acd03a699b0ddb5a2d481a8550977abb3313616752988cb"}, - {file = "invoice2data-0.3.5.tar.gz", hash = "sha256:c58ec7e46224dc3ffae72b17c05a5347fee1a13d9c17f6ee95f8bd16d1a2e791"}, + {file = "invoice2data-0.3.6-py3.9.egg", hash = "sha256:ff3b767056dfac473037d6caa1165e6a2b1c2683913d6df0a83a381f81ca48fa"}, + {file = "invoice2data-0.3.6.tar.gz", hash = "sha256:59d4c9e72cfb1577a74f25dd004c8d5d222bd3f82457489293c093bbec099761"}, ] iscompatible = [ {file = "iscompatible-0.1.1.tar.gz", hash = "sha256:0ef45bd23569df4ba01d66e4ab7a25f07db934bba235e706a85d26417d676f83"}, @@ -3115,9 +3396,9 @@ isodate = [ {file = "isodate-0.6.0-py2.py3-none-any.whl", hash = "sha256:aa4d33c06640f5352aca96e4b81afd8ab3b47337cc12089822d6f322ac772c81"}, {file = "isodate-0.6.0.tar.gz", hash = "sha256:2e364a3d5759479cdb2d37cce6b9376ea504db2ff90252a2e5b7cc89cc9ff2d8"}, ] -jdcal = [ - {file = "jdcal-1.4.1-py2.py3-none-any.whl", hash = "sha256:1abf1305fce18b4e8aa248cf8fe0c56ce2032392bc64bbd61b5dff2a19ec8bba"}, - {file = "jdcal-1.4.1.tar.gz", hash = "sha256:472872e096eb8df219c23f2689fc336668bdb43d194094b5cc1707e1640acfc8"}, +isort = [ + {file = "isort-5.9.1-py3-none-any.whl", hash = "sha256:8e2c107091cfec7286bc0f68a547d0ba4c094d460b732075b6fba674f1035c0c"}, + {file = "isort-5.9.1.tar.gz", hash = "sha256:83510593e07e433b77bd5bff0f6f607dbafa06d1a89022616f02d8b699cfcd56"}, ] jinja2 = [ {file = "Jinja2-2.10.1-py2.py3-none-any.whl", hash = "sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"}, @@ -3131,6 +3412,14 @@ jmespath = [ {file = "jmespath-0.10.0-py2.py3-none-any.whl", hash = "sha256:cdf6525904cc597730141d61b36f2e4b8ecc257c420fa2f4549bac2c2d0cb72f"}, {file = "jmespath-0.10.0.tar.gz", hash = "sha256:b85d0567b8666149a93172712e68920734333c0ce7e89b78b3e987f71e5ed4f9"}, ] +js2py = [ + {file = "Js2Py-0.71-py3-none-any.whl", hash = "sha256:7f3dfa30c4b8e3ac3edd64c361c950a8c2587a30a86854aeb8c1ffb6f4dd24b4"}, + {file = "Js2Py-0.71.tar.gz", hash = "sha256:a41b1009dd1498ae7d436bfa5ac952a08ca92a4bb9e31dca6e8bb966b49f7fce"}, +] +jsonlines = [ + {file = "jsonlines-2.0.0-py3-none-any.whl", hash = "sha256:bfb043d4e25fd894dca67b1f2adf014e493cb65d0f18b3a74a98bfcd97c3d983"}, + {file = "jsonlines-2.0.0.tar.gz", hash = "sha256:6fdd03104c9a421a1ba587a121aaac743bf02d8f87fa9cdaa3b852249a241fe8"}, +] jsonschema = [ {file = "jsonschema-3.2.0-py2.py3-none-any.whl", hash = "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163"}, {file = "jsonschema-3.2.0.tar.gz", hash = "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"}, @@ -3166,6 +3455,30 @@ kiwisolver = [ lasso = [ {file = "lasso-0.0.5.tar.gz", hash = "sha256:e64abaeef6f3e3e5f669cc44ca1423e69ad59360625269f50ee6ecb2172aa824"}, ] +lazy-object-proxy = [ + {file = "lazy-object-proxy-1.6.0.tar.gz", hash = "sha256:489000d368377571c6f982fba6497f2aa13c6d1facc40660963da62f5c379726"}, + {file = "lazy_object_proxy-1.6.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:c6938967f8528b3668622a9ed3b31d145fab161a32f5891ea7b84f6b790be05b"}, + {file = "lazy_object_proxy-1.6.0-cp27-cp27m-win32.whl", hash = "sha256:ebfd274dcd5133e0afae738e6d9da4323c3eb021b3e13052d8cbd0e457b1256e"}, + {file = "lazy_object_proxy-1.6.0-cp27-cp27m-win_amd64.whl", hash = "sha256:ed361bb83436f117f9917d282a456f9e5009ea12fd6de8742d1a4752c3017e93"}, + {file = "lazy_object_proxy-1.6.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d900d949b707778696fdf01036f58c9876a0d8bfe116e8d220cfd4b15f14e741"}, + {file = "lazy_object_proxy-1.6.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5743a5ab42ae40caa8421b320ebf3a998f89c85cdc8376d6b2e00bd12bd1b587"}, + {file = "lazy_object_proxy-1.6.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:bf34e368e8dd976423396555078def5cfc3039ebc6fc06d1ae2c5a65eebbcde4"}, + {file = "lazy_object_proxy-1.6.0-cp36-cp36m-win32.whl", hash = "sha256:b579f8acbf2bdd9ea200b1d5dea36abd93cabf56cf626ab9c744a432e15c815f"}, + {file = "lazy_object_proxy-1.6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:4f60460e9f1eb632584c9685bccea152f4ac2130e299784dbaf9fae9f49891b3"}, + {file = "lazy_object_proxy-1.6.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d7124f52f3bd259f510651450e18e0fd081ed82f3c08541dffc7b94b883aa981"}, + {file = "lazy_object_proxy-1.6.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:22ddd618cefe54305df49e4c069fa65715be4ad0e78e8d252a33debf00f6ede2"}, + {file = "lazy_object_proxy-1.6.0-cp37-cp37m-win32.whl", hash = "sha256:9d397bf41caad3f489e10774667310d73cb9c4258e9aed94b9ec734b34b495fd"}, + {file = "lazy_object_proxy-1.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:24a5045889cc2729033b3e604d496c2b6f588c754f7a62027ad4437a7ecc4837"}, + {file = "lazy_object_proxy-1.6.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:17e0967ba374fc24141738c69736da90e94419338fd4c7c7bef01ee26b339653"}, + {file = "lazy_object_proxy-1.6.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:410283732af311b51b837894fa2f24f2c0039aa7f220135192b38fcc42bd43d3"}, + {file = "lazy_object_proxy-1.6.0-cp38-cp38-win32.whl", hash = "sha256:85fb7608121fd5621cc4377a8961d0b32ccf84a7285b4f1d21988b2eae2868e8"}, + {file = "lazy_object_proxy-1.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:d1c2676e3d840852a2de7c7d5d76407c772927addff8d742b9808fe0afccebdf"}, + {file = "lazy_object_proxy-1.6.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:b865b01a2e7f96db0c5d12cfea590f98d8c5ba64ad222300d93ce6ff9138bcad"}, + {file = "lazy_object_proxy-1.6.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:4732c765372bd78a2d6b2150a6e99d00a78ec963375f236979c0626b97ed8e43"}, + {file = "lazy_object_proxy-1.6.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:9698110e36e2df951c7c36b6729e96429c9c32b3331989ef19976592c5f3c77a"}, + {file = "lazy_object_proxy-1.6.0-cp39-cp39-win32.whl", hash = "sha256:1fee665d2638491f4d6e55bd483e15ef21f6c8c2095f235fef72601021e64f61"}, + {file = "lazy_object_proxy-1.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:f5144c75445ae3ca2057faac03fda5a902eff196702b0a24daf1d6ce0650514b"}, +] leven = [ {file = "leven-1.0.4.tar.gz", hash = "sha256:732474a3b9e94003aab61fd57eb2cbdaf0ed32f9a85b63073bcc4fa1ed5d0aff"}, ] @@ -3241,14 +3554,14 @@ matplotlib = [ {file = "matplotlib-3.2.2-pp36-pypy36_pp73-win32.whl", hash = "sha256:67065d938df34478451af62fbd0670d2b51c4d859fb66673064eb5de8660dd7c"}, {file = "matplotlib-3.2.2.tar.gz", hash = "sha256:3d77a6630d093d74cbbfebaa0571d00790966be1ed204e4a8239f5cbd6835c5d"}, ] +mccabe = [ + {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, + {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, +] mock = [ {file = "mock-2.0.0-py2.py3-none-any.whl", hash = "sha256:5ce3c71c5545b472da17b72268978914d0252980348636840bd34a00b5cc96c1"}, {file = "mock-2.0.0.tar.gz", hash = "sha256:b158b6df76edd239b8208d481dc46b6afd45a846b7812ff0ce58971cf5bc8bba"}, ] -monotonic = [ - {file = "monotonic-1.5-py2.py3-none-any.whl", hash = "sha256:552a91f381532e33cbd07c6a2655a21908088962bb8fa7239ecbcc6ad1140cc7"}, - {file = "monotonic-1.5.tar.gz", hash = "sha256:23953d55076df038541e648a53676fb24980f7a1be290cdda21300b3bc21dfb0"}, -] mpld3 = [ {file = "mpld3-0.3.tar.gz", hash = "sha256:4d455884a211bf99b37ecc760759435c7bb6a5955de47d8daf4967e301878ab7"}, ] @@ -3291,6 +3604,10 @@ multidict = [ {file = "multidict-4.7.6-cp38-cp38-win_amd64.whl", hash = "sha256:7388d2ef3c55a8ba80da62ecfafa06a1c097c18032a501ffd4cabbc52d7f2b19"}, {file = "multidict-4.7.6.tar.gz", hash = "sha256:fbb77a75e529021e7c4a8d4e823d88ef4d23674a202be4f5addffc72cbb91430"}, ] +mypy-extensions = [ + {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, + {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, +] mysqlclient = [ {file = "mysqlclient-2.0.3-cp36-cp36m-win_amd64.whl", hash = "sha256:3381ca1a4f37ff1155fcfde20836b46416d66531add8843f6aa6d968982731c3"}, {file = "mysqlclient-2.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:0ac0dd759c4ca02c35a9fedc24bc982cf75171651e8187c2495ec957a87dfff7"}, @@ -3298,9 +3615,6 @@ mysqlclient = [ {file = "mysqlclient-2.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:fc575093cf81b6605bed84653e48b277318b880dc9becf42dd47fa11ffd3e2b6"}, {file = "mysqlclient-2.0.3.tar.gz", hash = "sha256:f6ebea7c008f155baeefe16c56cd3ee6239f7a5a9ae42396c2f1860f08a7c432"}, ] -naturalsort = [ - {file = "naturalsort-1.5.1.tar.gz", hash = "sha256:172b5ed6e7ba3420c08ba2ded1c52fe74878f5d769dc5d9dec2b6a53e7117356"}, -] netaddr = [ {file = "netaddr-0.8.0-py2.py3-none-any.whl", hash = "sha256:9666d0232c32d2656e5e5f8d735f58fd6c7457ce52fc21c98d45f2af78f990ac"}, {file = "netaddr-0.8.0.tar.gz", hash = "sha256:d6cc57c7a07b1d9d2e917aa8b36ae8ce61c35ba3fcd1b83ca31c5a0ee2b5a243"}, @@ -3339,40 +3653,34 @@ num2words = [ {file = "num2words-0.5.6.tar.gz", hash = "sha256:aea26c2d11d636f0e9da094f2bf55ac94cb1c380ff1f86e8db22c210e5a6a05f"}, ] numpy = [ - {file = "numpy-1.19.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cc6bd4fd593cb261332568485e20a0712883cf631f6f5e8e86a52caa8b2b50ff"}, - {file = "numpy-1.19.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:aeb9ed923be74e659984e321f609b9ba54a48354bfd168d21a2b072ed1e833ea"}, - {file = "numpy-1.19.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8b5e972b43c8fc27d56550b4120fe6257fdc15f9301914380b27f74856299fea"}, - {file = "numpy-1.19.5-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:43d4c81d5ffdff6bae58d66a3cd7f54a7acd9a0e7b18d97abb255defc09e3140"}, - {file = "numpy-1.19.5-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:a4646724fba402aa7504cd48b4b50e783296b5e10a524c7a6da62e4a8ac9698d"}, - {file = "numpy-1.19.5-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:2e55195bc1c6b705bfd8ad6f288b38b11b1af32f3c8289d6c50d47f950c12e76"}, - {file = "numpy-1.19.5-cp36-cp36m-win32.whl", hash = "sha256:39b70c19ec771805081578cc936bbe95336798b7edf4732ed102e7a43ec5c07a"}, - {file = "numpy-1.19.5-cp36-cp36m-win_amd64.whl", hash = "sha256:dbd18bcf4889b720ba13a27ec2f2aac1981bd41203b3a3b27ba7a33f88ae4827"}, - {file = "numpy-1.19.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:603aa0706be710eea8884af807b1b3bc9fb2e49b9f4da439e76000f3b3c6ff0f"}, - {file = "numpy-1.19.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:cae865b1cae1ec2663d8ea56ef6ff185bad091a5e33ebbadd98de2cfa3fa668f"}, - {file = "numpy-1.19.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:36674959eed6957e61f11c912f71e78857a8d0604171dfd9ce9ad5cbf41c511c"}, - {file = "numpy-1.19.5-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:06fab248a088e439402141ea04f0fffb203723148f6ee791e9c75b3e9e82f080"}, - {file = "numpy-1.19.5-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6149a185cece5ee78d1d196938b2a8f9d09f5a5ebfbba66969302a778d5ddd1d"}, - {file = "numpy-1.19.5-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:50a4a0ad0111cc1b71fa32dedd05fa239f7fb5a43a40663269bb5dc7877cfd28"}, - {file = "numpy-1.19.5-cp37-cp37m-win32.whl", hash = "sha256:d051ec1c64b85ecc69531e1137bb9751c6830772ee5c1c426dbcfe98ef5788d7"}, - {file = "numpy-1.19.5-cp37-cp37m-win_amd64.whl", hash = "sha256:a12ff4c8ddfee61f90a1633a4c4afd3f7bcb32b11c52026c92a12e1325922d0d"}, - {file = "numpy-1.19.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cf2402002d3d9f91c8b01e66fbb436a4ed01c6498fffed0e4c7566da1d40ee1e"}, - {file = "numpy-1.19.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1ded4fce9cfaaf24e7a0ab51b7a87be9038ea1ace7f34b841fe3b6894c721d1c"}, - {file = "numpy-1.19.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:012426a41bc9ab63bb158635aecccc7610e3eff5d31d1eb43bc099debc979d94"}, - {file = "numpy-1.19.5-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:759e4095edc3c1b3ac031f34d9459fa781777a93ccc633a472a5468587a190ff"}, - {file = "numpy-1.19.5-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:a9d17f2be3b427fbb2bce61e596cf555d6f8a56c222bd2ca148baeeb5e5c783c"}, - {file = "numpy-1.19.5-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:99abf4f353c3d1a0c7a5f27699482c987cf663b1eac20db59b8c7b061eabd7fc"}, - {file = "numpy-1.19.5-cp38-cp38-win32.whl", hash = "sha256:384ec0463d1c2671170901994aeb6dce126de0a95ccc3976c43b0038a37329c2"}, - {file = "numpy-1.19.5-cp38-cp38-win_amd64.whl", hash = "sha256:811daee36a58dc79cf3d8bdd4a490e4277d0e4b7d103a001a4e73ddb48e7e6aa"}, - {file = "numpy-1.19.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c843b3f50d1ab7361ca4f0b3639bf691569493a56808a0b0c54a051d260b7dbd"}, - {file = "numpy-1.19.5-cp39-cp39-manylinux1_i686.whl", hash = "sha256:d6631f2e867676b13026e2846180e2c13c1e11289d67da08d71cacb2cd93d4aa"}, - {file = "numpy-1.19.5-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7fb43004bce0ca31d8f13a6eb5e943fa73371381e53f7074ed21a4cb786c32f8"}, - {file = "numpy-1.19.5-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:2ea52bd92ab9f768cc64a4c3ef8f4b2580a17af0a5436f6126b08efbd1838371"}, - {file = "numpy-1.19.5-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:400580cbd3cff6ffa6293df2278c75aef2d58d8d93d3c5614cd67981dae68ceb"}, - {file = "numpy-1.19.5-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:df609c82f18c5b9f6cb97271f03315ff0dbe481a2a02e56aeb1b1a985ce38e60"}, - {file = "numpy-1.19.5-cp39-cp39-win32.whl", hash = "sha256:ab83f24d5c52d60dbc8cd0528759532736b56db58adaa7b5f1f76ad551416a1e"}, - {file = "numpy-1.19.5-cp39-cp39-win_amd64.whl", hash = "sha256:0eef32ca3132a48e43f6a0f5a82cb508f22ce5a3d6f67a8329c81c8e226d3f6e"}, - {file = "numpy-1.19.5-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:a0d53e51a6cb6f0d9082decb7a4cb6dfb33055308c4c44f53103c073f649af73"}, - {file = "numpy-1.19.5.zip", hash = "sha256:a76f502430dd98d7546e1ea2250a7360c065a5fdea52b2dffe8ae7180909b6f4"}, + {file = "numpy-1.21.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d5caa946a9f55511e76446e170bdad1d12d6b54e17a2afe7b189112ed4412bb8"}, + {file = "numpy-1.21.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ac4fd578322842dbda8d968e3962e9f22e862b6ec6e3378e7415625915e2da4d"}, + {file = "numpy-1.21.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:598fe100b2948465cf3ed64b1a326424b5e4be2670552066e17dfaa67246011d"}, + {file = "numpy-1.21.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c55407f739f0bfcec67d0df49103f9333edc870061358ac8a8c9e37ea02fcd2"}, + {file = "numpy-1.21.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:75579acbadbf74e3afd1153da6177f846212ea2a0cc77de53523ae02c9256513"}, + {file = "numpy-1.21.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cc367c86eb87e5b7c9592935620f22d13b090c609f1b27e49600cd033b529f54"}, + {file = "numpy-1.21.0-cp37-cp37m-win32.whl", hash = "sha256:d89b0dc7f005090e32bb4f9bf796e1dcca6b52243caf1803fdd2b748d8561f63"}, + {file = "numpy-1.21.0-cp37-cp37m-win_amd64.whl", hash = "sha256:eda2829af498946c59d8585a9fd74da3f810866e05f8df03a86f70079c7531dd"}, + {file = "numpy-1.21.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:1a784e8ff7ea2a32e393cc53eb0003eca1597c7ca628227e34ce34eb11645a0e"}, + {file = "numpy-1.21.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bba474a87496d96e61461f7306fba2ebba127bed7836212c360f144d1e72ac54"}, + {file = "numpy-1.21.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fd0a359c1c17f00cb37de2969984a74320970e0ceef4808c32e00773b06649d9"}, + {file = "numpy-1.21.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e4d5a86a5257843a18fb1220c5f1c199532bc5d24e849ed4b0289fb59fbd4d8f"}, + {file = "numpy-1.21.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:620732f42259eb2c4642761bd324462a01cdd13dd111740ce3d344992dd8492f"}, + {file = "numpy-1.21.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9205711e5440954f861ceeea8f1b415d7dd15214add2e878b4d1cf2bcb1a914"}, + {file = "numpy-1.21.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ad09f55cc95ed8d80d8ab2052f78cc21cb231764de73e229140d81ff49d8145e"}, + {file = "numpy-1.21.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a1f2fb2da242568af0271455b89aee0f71e4e032086ee2b4c5098945d0e11cf6"}, + {file = "numpy-1.21.0-cp38-cp38-win32.whl", hash = "sha256:e58ddb53a7b4959932f5582ac455ff90dcb05fac3f8dcc8079498d43afbbde6c"}, + {file = "numpy-1.21.0-cp38-cp38-win_amd64.whl", hash = "sha256:d2910d0a075caed95de1a605df00ee03b599de5419d0b95d55342e9a33ad1fb3"}, + {file = "numpy-1.21.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a290989cd671cd0605e9c91a70e6df660f73ae87484218e8285c6522d29f6e38"}, + {file = "numpy-1.21.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3537b967b350ad17633b35c2f4b1a1bbd258c018910b518c30b48c8e41272717"}, + {file = "numpy-1.21.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ccc6c650f8700ce1e3a77668bb7c43e45c20ac06ae00d22bdf6760b38958c883"}, + {file = "numpy-1.21.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:709884863def34d72b183d074d8ba5cfe042bc3ff8898f1ffad0209161caaa99"}, + {file = "numpy-1.21.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bebab3eaf0641bba26039fb0b2c5bf9b99407924b53b1ea86e03c32c64ef5aef"}, + {file = "numpy-1.21.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf680682ad0a3bef56dae200dbcbac2d57294a73e5b0f9864955e7dd7c2c2491"}, + {file = "numpy-1.21.0-cp39-cp39-win32.whl", hash = "sha256:d95d16204cd51ff1a1c8d5f9958ce90ae190be81d348b514f9be39f878b8044a"}, + {file = "numpy-1.21.0-cp39-cp39-win_amd64.whl", hash = "sha256:2ba579dde0563f47021dcd652253103d6fd66165b18011dce1a0609215b2791e"}, + {file = "numpy-1.21.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3c40e6b860220ed862e8097b8f81c9af6d7405b723f4a7af24a267b46f90e461"}, + {file = "numpy-1.21.0.zip", hash = "sha256:e80fe25cba41c124d04c662f33f6364909b985f2eb5998aaa5ae4b9587242cce"}, ] oauthlib = [ {file = "oauthlib-2.1.0-py2.py3-none-any.whl", hash = "sha256:d883b36b21a6ad813953803edfa563b1b579d79ca758fe950d1bc9e8b326025b"}, @@ -3390,8 +3698,8 @@ olefile = [ {file = "olefile-0.46.zip", hash = "sha256:133b031eaf8fd2c9399b78b8bc5b8fcbe4c31e85295749bb17a87cba8f3c3964"}, ] openpyxl = [ - {file = "openpyxl-3.0.5-py2.py3-none-any.whl", hash = "sha256:f7d666b569f729257082cf7ddc56262431878f602dcc2bc3980775c59439cdab"}, - {file = "openpyxl-3.0.5.tar.gz", hash = "sha256:18e11f9a650128a12580a58e3daba14e00a11d9e907c554a17ea016bf1a2c71b"}, + {file = "openpyxl-3.0.7-py2.py3-none-any.whl", hash = "sha256:46af4eaf201a89b610fcca177eed957635f88770a5462fb6aae4a2a52b0ff516"}, + {file = "openpyxl-3.0.7.tar.gz", hash = "sha256:6456a3b472e1ef0facb1129f3c6ef00713cebf62e736cd7a75bcc3247432f251"}, ] openupgradelib = [ {file = "openupgradelib-2.0.0.tar.gz", hash = "sha256:acb826ed5965db388d086a6585afb63aee89719082ea7ab8142fc170c02ff257"}, @@ -3452,21 +3760,28 @@ passlib = [ {file = "passlib-1.6.5-py2.py3-none-any.whl", hash = "sha256:ad631a58dc8abeb0f48016c13f4b3b0f3a7b1045a8cb3c61dd15e2d95b45c472"}, {file = "passlib-1.6.5.tar.gz", hash = "sha256:a83d34f53dc9b17aa42c9a35c3fbcc5120f3fcb07f7f8721ec45e6a27be347fc"}, ] +pathspec = [ + {file = "pathspec-0.8.1-py2.py3-none-any.whl", hash = "sha256:aa0cb481c4041bf52ffa7b0d8fa6cd3e88a2ca4879c533c9153882ee2556790d"}, + {file = "pathspec-0.8.1.tar.gz", hash = "sha256:86379d6b86d75816baba717e64b1a3a3469deb93bb76d613c9ce79edc5cb68fd"}, +] pbr = [ {file = "pbr-5.4.5-py2.py3-none-any.whl", hash = "sha256:579170e23f8e0c2f24b0de612f71f648eccb79fb1322c814ae6b3c07b5ba23e8"}, {file = "pbr-5.4.5.tar.gz", hash = "sha256:07f558fece33b05caf857474a366dfcc00562bca13dd8b47b2b3e22d9f9bf55c"}, ] pdf2image = [ - {file = "pdf2image-1.14.0-py3-none-any.whl", hash = "sha256:cf1b2dc77cf3e050cb06078cd7373469c8dca93d4cea1af2a2e1bbe0ed4a8800"}, - {file = "pdf2image-1.14.0.tar.gz", hash = "sha256:066527e1bf954762fb4369c677ae3bc15f2ce8707eee830cccef8471fde736d7"}, + {file = "pdf2image-1.16.0-py3-none-any.whl", hash = "sha256:84f79f2b8fad943e36323ea4e937fcb05f26ded0caa0a01181df66049e42fb65"}, + {file = "pdf2image-1.16.0.tar.gz", hash = "sha256:d58ed94d978a70c73c2bb7fdf8acbaf2a7089c29ff8141be5f45433c0c4293bb"}, +] +pdfminer = [ + {file = "pdfminer-20191125.tar.gz", hash = "sha256:9e700bc731300ed5c8936343c1dd4529638184198e54e91dd2b59b64a755dc01"}, ] pexpect = [ {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, ] phonenumbers = [ - {file = "phonenumbers-8.12.15-py2.py3-none-any.whl", hash = "sha256:13d499f7114c4b37c54ee844b188d5e7441951a7da41de5fc1a25ff8fdceef80"}, - {file = "phonenumbers-8.12.15.tar.gz", hash = "sha256:b734bfcf33e87ddae72196a40b3d1af35abd0beb263816ae18e1bff612926406"}, + {file = "phonenumbers-8.12.26-py2.py3-none-any.whl", hash = "sha256:37299bddabd81ce34fee97e1c95da49f2742b8240710d88649cfcfde3dc73ff2"}, + {file = "phonenumbers-8.12.26.tar.gz", hash = "sha256:65bab6ebdbe0ec5196c74626949748db5337d23895aabc1ef8f5d7284787998a"}, ] pillow = [ {file = "Pillow-6.1.0-cp27-cp27m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:76638865c83b1bb33bcac2a61ce4d13c17dba2204969dedb9ab60ef62bede686"}, @@ -3517,13 +3832,16 @@ plotly = [ {file = "plotly-4.1.0-py2.py3-none-any.whl", hash = "sha256:c5effc51364490b1a20fe7bb8443cfe2451004fca727c7f3fedbc30f4cef5aab"}, {file = "plotly-4.1.0.tar.gz", hash = "sha256:9333f28feacaa0751df04cccfb266463bf5029dcb106d3f81d7af5942fd3d998"}, ] -premailer = [ - {file = "premailer-3.7.0-py2.py3-none-any.whl", hash = "sha256:c7ac48986984a810afea5147bc8410a8fe0659bf52f357e78b28a1b949209b91"}, - {file = "premailer-3.7.0.tar.gz", hash = "sha256:5eec9603e84cee583a390de69c75192e50d76e38ef0292b027bd64923766aca7"}, +ply = [ + {file = "ply-3.4.tar.gz", hash = "sha256:af435f11b7bdd69da5ffbc3fecb8d70a7073ec952e101764c88720cdefb2546b"}, ] -property-manager = [ - {file = "property-manager-3.0.tar.gz", hash = "sha256:93e76da9ae7af13cccc2cd1e3b47219950c56c125cd962aaed693894af267c54"}, - {file = "property_manager-3.0-py2.py3-none-any.whl", hash = "sha256:d5d648053e669cf9cb2f157e4a41ef46174eaa8ee13bfa49e1530c17d65bfe45"}, +polib = [ + {file = "polib-1.1.0-py2.py3-none-any.whl", hash = "sha256:93b730477c16380c9a96726c54016822ff81acfa553977fdd131f2b90ba858d7"}, + {file = "polib-1.1.0.tar.gz", hash = "sha256:fad87d13696127ffb27ea0882d6182f1a9cf8a5e2b37a587751166c51e5a332a"}, +] +premailer = [ + {file = "premailer-3.9.0-py2.py3-none-any.whl", hash = "sha256:d674826981be58d2eaa51db25f31bfe02f2859760aa1ff9879de9110f48e6476"}, + {file = "premailer-3.9.0.tar.gz", hash = "sha256:da18b9e8cb908893b67ab9b7451276fef7c0ab179f40189378545f6bb0ab3695"}, ] psutil = [ {file = "psutil-4.3.1-cp27-none-win32.whl", hash = "sha256:b0c5bf0d2a29a6f18ac22e2d24210730dca458c9f961914289c9e027ccb5ae43"}, @@ -3594,6 +3912,10 @@ py-asterisk = [ {file = "py3o.template-0.10.0-py3-none-any.whl", hash = "sha256:b83c43d1ff89ec9688e0c9c5297b0afdb0ecb123c6b2311e4d173aa36920b4e2"}, {file = "py3o.template-0.10.0.tar.gz", hash = "sha256:ea544e76ad519172fc49a621e999a1438fc8aa8869762db913fbc336518606d3"}, ] +pycodestyle = [ + {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"}, + {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"}, +] pycountry = [ {file = "pycountry-20.7.3.tar.gz", hash = "sha256:81084a53d3454344c0292deebc20fcd0a1488c136d4900312cbd465cf552cb42"}, ] @@ -3601,9 +3923,45 @@ pycparser = [ {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, ] +pycryptodome = [ + {file = "pycryptodome-3.10.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1c5e1ca507de2ad93474be5cfe2bfa76b7cf039a1a32fc196f40935944871a06"}, + {file = "pycryptodome-3.10.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:6260e24d41149268122dd39d4ebd5941e9d107f49463f7e071fd397e29923b0c"}, + {file = "pycryptodome-3.10.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:3f840c49d38986f6e17dbc0673d37947c88bc9d2d9dba1c01b979b36f8447db1"}, + {file = "pycryptodome-3.10.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:2dea65df54349cdfa43d6b2e8edb83f5f8d6861e5cf7b1fbc3e34c5694c85e27"}, + {file = "pycryptodome-3.10.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:e61e363d9a5d7916f3a4ce984a929514c0df3daf3b1b2eb5e6edbb131ee771cf"}, + {file = "pycryptodome-3.10.1-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:2603c98ae04aac675fefcf71a6c87dc4bb74a75e9071ae3923bbc91a59f08d35"}, + {file = "pycryptodome-3.10.1-cp27-cp27m-win32.whl", hash = "sha256:38661348ecb71476037f1e1f553159b80d256c00f6c0b00502acac891f7116d9"}, + {file = "pycryptodome-3.10.1-cp27-cp27m-win_amd64.whl", hash = "sha256:1723ebee5561628ce96748501cdaa7afaa67329d753933296321f0be55358dce"}, + {file = "pycryptodome-3.10.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:77997519d8eb8a4adcd9a47b9cec18f9b323e296986528186c0e9a7a15d6a07e"}, + {file = "pycryptodome-3.10.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:99b2f3fc51d308286071d0953f92055504a6ffe829a832a9fc7a04318a7683dd"}, + {file = "pycryptodome-3.10.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:e0a4d5933a88a2c98bbe19c0c722f5483dc628d7a38338ac2cb64a7dbd34064b"}, + {file = "pycryptodome-3.10.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d3d6958d53ad307df5e8469cc44474a75393a434addf20ecd451f38a72fe29b8"}, + {file = "pycryptodome-3.10.1-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:a8eb8b6ea09ec1c2535bf39914377bc8abcab2c7d30fa9225eb4fe412024e427"}, + {file = "pycryptodome-3.10.1-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:31c1df17b3dc5f39600a4057d7db53ac372f492c955b9b75dd439f5d8b460129"}, + {file = "pycryptodome-3.10.1-cp35-abi3-manylinux1_i686.whl", hash = "sha256:a3105a0eb63eacf98c2ecb0eb4aa03f77f40fbac2bdde22020bb8a536b226bb8"}, + {file = "pycryptodome-3.10.1-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:a92d5c414e8ee1249e850789052608f582416e82422502dc0ac8c577808a9067"}, + {file = "pycryptodome-3.10.1-cp35-abi3-manylinux2010_i686.whl", hash = "sha256:60386d1d4cfaad299803b45a5bc2089696eaf6cdd56f9fc17479a6f89595cfc8"}, + {file = "pycryptodome-3.10.1-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:501ab36aae360e31d0ec370cf5ce8ace6cb4112060d099b993bc02b36ac83fb6"}, + {file = "pycryptodome-3.10.1-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:fc7489a50323a0df02378bc2fff86eb69d94cc5639914346c736be981c6a02e7"}, + {file = "pycryptodome-3.10.1-cp35-abi3-win32.whl", hash = "sha256:9b6f711b25e01931f1c61ce0115245a23cdc8b80bf8539ac0363bdcf27d649b6"}, + {file = "pycryptodome-3.10.1-cp35-abi3-win_amd64.whl", hash = "sha256:7fd519b89585abf57bf47d90166903ec7b43af4fe23c92273ea09e6336af5c07"}, + {file = "pycryptodome-3.10.1-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:09c1555a3fa450e7eaca41ea11cd00afe7c91fef52353488e65663777d8524e0"}, + {file = "pycryptodome-3.10.1-pp27-pypy_73-manylinux1_x86_64.whl", hash = "sha256:758949ca62690b1540dfb24ad773c6da9cd0e425189e83e39c038bbd52b8e438"}, + {file = "pycryptodome-3.10.1-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:e3bf558c6aeb49afa9f0c06cee7fb5947ee5a1ff3bd794b653d39926b49077fa"}, + {file = "pycryptodome-3.10.1-pp27-pypy_73-win32.whl", hash = "sha256:f977cdf725b20f6b8229b0c87acb98c7717e742ef9f46b113985303ae12a99da"}, + {file = "pycryptodome-3.10.1-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6d2df5223b12437e644ce0a3be7809471ffa71de44ccd28b02180401982594a6"}, + {file = "pycryptodome-3.10.1-pp36-pypy36_pp73-manylinux1_x86_64.whl", hash = "sha256:98213ac2b18dc1969a47bc65a79a8fca02a414249d0c8635abb081c7f38c91b6"}, + {file = "pycryptodome-3.10.1-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:12222a5edc9ca4a29de15fbd5339099c4c26c56e13c2ceddf0b920794f26165d"}, + {file = "pycryptodome-3.10.1-pp36-pypy36_pp73-win32.whl", hash = "sha256:6bbf7fee7b7948b29d7e71fcacf48bac0c57fb41332007061a933f2d996f9713"}, + {file = "pycryptodome-3.10.1.tar.gz", hash = "sha256:3e2e3a06580c5f190df843cdb90ea28d61099cf4924334d5297a995de68e4673"}, +] pydot = [ {file = "pydot-1.2.3.tar.gz", hash = "sha256:edb5d3f249f97fbd9c4bb16959e61bc32ecf40eee1a9f6d27abe8d01c0a73502"}, ] +pyflakes = [ + {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"}, + {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"}, +] pygments = [ {file = "Pygments-2.6.1-py3-none-any.whl", hash = "sha256:ff7a40b4860b727ab48fad6360eb351cc1b33cbf9b15a0f689ca5353e9463324"}, {file = "Pygments-2.6.1.tar.gz", hash = "sha256:647344a061c249a3b74e230c739f434d7ea4d8b1d5f3721bc0f3558049b38f44"}, @@ -3619,6 +3977,10 @@ pygount = [ {file = "pyjon.utils-0.7.tar.gz", hash = "sha256:c2759ea361e00ef272ab65eb7af353398361d122f956efbf6a0241018f702d89"}, {file = "pyjon.utils-0.7.zip", hash = "sha256:d360fb393c2cf87ded962480895c83bc8c4f05f5b2ce7788bc5f16a67452bc2d"}, ] +pyjsparser = [ + {file = "pyjsparser-2.7.1-py2-none-any.whl", hash = "sha256:2b12842df98d83f65934e0772fa4a5d8b123b3bc79f1af1789172ac70265dd21"}, + {file = "pyjsparser-2.7.1.tar.gz", hash = "sha256:be60da6b778cc5a5296a69d8e7d614f1f870faf94e1b1b6ac591f2ad5d729579"}, +] pyjwt = [ {file = "PyJWT-1.7.1-py2.py3-none-any.whl", hash = "sha256:5c6eca3c2940464d106b99ba83b00c6add741c9becaec087fb7ccdefea71350e"}, {file = "PyJWT-1.7.1.tar.gz", hash = "sha256:8d59a976fb773f3e6a39c85636357c4f0e242707394cadadd9814f5cbaa20e96"}, @@ -3626,36 +3988,58 @@ pyjwt = [ pyldap = [ {file = "pyldap-2.4.28.tar.gz", hash = "sha256:d38f31018f0c15925f50aec39f7255c15463f98797af53931e0e2a9ac21f6661"}, ] +pylint = [ + {file = "pylint-2.6.0-py3-none-any.whl", hash = "sha256:bfe68f020f8a0fece830a22dd4d5dddb4ecc6137db04face4c3420a46a52239f"}, + {file = "pylint-2.6.0.tar.gz", hash = "sha256:bb4a908c9dadbc3aac18860550e870f58e1a02c9f2c204fdf5693d73be061210"}, +] +pylint-odoo = [] +pylint-plugin-utils = [ + {file = "pylint-plugin-utils-0.6.tar.gz", hash = "sha256:57625dcca20140f43731311cd8fd879318bf45a8b0fd17020717a8781714a25a"}, + {file = "pylint_plugin_utils-0.6-py3-none-any.whl", hash = "sha256:2f30510e1c46edf268d3a195b2849bd98a1b9433229bb2ba63b8d776e1fc4d0a"}, +] pymssql = [ - {file = "pymssql-2.1.5-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:cff8e775fb6294effeb716735bfd7707e79a2a79b617d0f1984bd574f26bda65"}, - {file = "pymssql-2.1.5-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:c47c093cc4dc60e3356458c8e2935bab3834cea1f94a66c8ca62a5af2f060d64"}, - {file = "pymssql-2.1.5-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:658b4ea09050c85c6be09e1371335198b9441d2b5b08ef4f0b250ee4e5e8afc3"}, - {file = "pymssql-2.1.5-cp27-cp27m-win32.whl", hash = "sha256:f36392e1874445d7cb67b928686ad424b0b3980282512b21f640828ad3adf968"}, - {file = "pymssql-2.1.5-cp27-cp27m-win_amd64.whl", hash = "sha256:4fd4991eee848a4fd7d0b19a24fe49b508633881e221004652ab15a7e4cfe041"}, - {file = "pymssql-2.1.5-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:cfd9ae0484056e46b981b7c3893ddb620ccd52f48349bada78cb141192dfbfbe"}, - {file = "pymssql-2.1.5-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:36539e42e8bb33018a05f9bd524b5a76286132ab7c82bfe9b60c4169d460fdf5"}, - {file = "pymssql-2.1.5-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:18b6550a02b34e88134b4b70eedcc6982036e459b0c91c7dd248bb1926287264"}, - {file = "pymssql-2.1.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c7a715c0b2b3a37462a9cf7972ed9ef0be98b2c64aebd549359f08af7f53b9a9"}, - {file = "pymssql-2.1.5-cp35-cp35m-win32.whl", hash = "sha256:e4741c6ec0483dcadb8a63077a7ceb17f263d9815ea842fed6663508c8852d7f"}, - {file = "pymssql-2.1.5-cp35-cp35m-win_amd64.whl", hash = "sha256:3e077455a11fcb4cb8705cb3ae83236b8e130df9fd4186c707d638e8e43f9646"}, - {file = "pymssql-2.1.5-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:0ff55a944ee7506a5e9aef7b40f0cddabc0b61f9ba13d716bff5a308923b8111"}, - {file = "pymssql-2.1.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:3bdbeca64af7856923b7f84ed3355e2fd00bb1b897877b0bd4a74ec638801d52"}, - {file = "pymssql-2.1.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:dfc764a5a07197d742da34a593578295e9f8b64bb035c07e0981961672e18c85"}, - {file = "pymssql-2.1.5-cp36-cp36m-win32.whl", hash = "sha256:4f6d4434c29b846f491f5236daf06175f1652953d1d162be0f1b2b037bcf9a8d"}, - {file = "pymssql-2.1.5-cp36-cp36m-win_amd64.whl", hash = "sha256:aad5a1218691f83a16bab6dcfa24abf9da796abf5bf168a41972fe1cf93b3e37"}, - {file = "pymssql-2.1.5-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:1682ead549dcec31f3b8cc47da429572ea1c4b106cb4fa91df884f968123af93"}, - {file = "pymssql-2.1.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:ec28c73afde96def469c581208903cf035923dc6313b6916f80cbcc71f9413d1"}, - {file = "pymssql-2.1.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:fcf98e2c7cf18fa2fa09cdb7220849cd02e7b9481cb81ccdd8940da438f58d85"}, - {file = "pymssql-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:1e8d8abab391559b70f5df97fb22fc1d9ea627edcb943e558bdc7d7f455f93e2"}, - {file = "pymssql-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:e19a59eb8115418c3debcc9b685b2138d0abe6c9cb8c00bc2e738eb744bc6bda"}, - {file = "pymssql-2.1.5-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:2108114e4cc34ebbb8031df3e5579320e7569d51cd5094c5ddc333bf749d09a0"}, - {file = "pymssql-2.1.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:3977b056c5db8d01e74d88417cbb48e3e8bf03ab09ca6ef53790d025eae543df"}, - {file = "pymssql-2.1.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:d0f8094330523b8e4763a6903151bc35069309ccb57c61f87eeaa910a34f5a35"}, - {file = "pymssql-2.1.5-cp38-cp38-win32.whl", hash = "sha256:10f9b5b033eb30a38f4b36144eb4583fd478fd30afa9d64cd9a1965d22740446"}, - {file = "pymssql-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:557719b3ebc4617543de52eaadcdb6779f0c850e95b07be5f9775a2ef6a6c61f"}, - {file = "pymssql-2.1.5-cp39-cp39-manylinux1_i686.whl", hash = "sha256:04aab92d5a1a5d4e01a0797a939f103f02c0ef777bc8dcf1e952ed30dd1d43d4"}, - {file = "pymssql-2.1.5-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:70a5c67759254e982368c5b9ccfe076447a7fd545b8376eb62d60c3b85e3b94d"}, - {file = "pymssql-2.1.5.tar.gz", hash = "sha256:d60f5f90337399668e10ab6a23a1657f190c9585401eb96a5456261f7c414864"}, + {file = "pymssql-2.2.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:6fc382f253365f22286372a32cfeb5d380ad955045ae6f88cf372f758635557a"}, + {file = "pymssql-2.2.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:1032cc2bafb9edcb309ac526c359387b5d1e4c06c62a92872f8c28681883fe25"}, + {file = "pymssql-2.2.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:ecb95a2301375b4a48ba73fcfd664981d511904e552cfd2c17530ec03a5f502d"}, + {file = "pymssql-2.2.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:0dafb4b2cf4a1deace503656b917cc5f4dad7d600f7cfc5e16f10918727e369f"}, + {file = "pymssql-2.2.1-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:f293d4cb9c03e6d859c8f3afb6fa7a99b30fe8f42eafedfa21358b1d8a420165"}, + {file = "pymssql-2.2.1-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:9cbad4cd57ef67a32e55ead549da73ad5730ae5da0ace2a2206451897716ccfa"}, + {file = "pymssql-2.2.1-cp36-cp36m-manylinux_2_24_i686.whl", hash = "sha256:8ec909a71b239243d55fe59cbf8e25c8ef5dce3e3bac58c3aa0eaddaeffcd790"}, + {file = "pymssql-2.2.1-cp36-cp36m-manylinux_2_24_x86_64.whl", hash = "sha256:5a23654683698a26a8d45b239e19820ab9e4239aa52293e81a9ba9ddddf3006d"}, + {file = "pymssql-2.2.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:8bc05f632641e51d5782761622eee2538444fdbb39c9c0750ad76d8f650e6898"}, + {file = "pymssql-2.2.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:e8deccee711d1cdc8b6010622ced9d064bc943e5a0540616348768d4adc6e95e"}, + {file = "pymssql-2.2.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:379fcd412cf34a493b49cefd689f5f9f0878af57ce130dc47bd5dead8bb67f80"}, + {file = "pymssql-2.2.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:a579ae07dc7528385bf339261308e396bd483e68e770f84feb31032e18c72d2b"}, + {file = "pymssql-2.2.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:d4ff41cc76c3851e0410feaf96f7760c2eeb9fb84597baf47d7431124e66d6f8"}, + {file = "pymssql-2.2.1-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:f3201b11dafd073183b6237667d2224a3a1f1d1ef41c4f351b48a0779127ac40"}, + {file = "pymssql-2.2.1-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:7301d2da53b436e07f23f847172d9da8c1f506390b0ad4d32ad73527b67728ce"}, + {file = "pymssql-2.2.1-cp37-cp37m-manylinux_2_24_i686.whl", hash = "sha256:39c61b8104fbd4d9b1e74c7f2c90c3871d0f1ef82e1be177d544b207e44f1b4c"}, + {file = "pymssql-2.2.1-cp37-cp37m-manylinux_2_24_x86_64.whl", hash = "sha256:40d355603dd31258dd6de28351f504fcc4d70b715637c01ffb384fd9ba0189df"}, + {file = "pymssql-2.2.1-cp37-cp37m-win32.whl", hash = "sha256:3638ca82915d663acc7f898290bcc3e94a236ba56530b6959f821334977bf56e"}, + {file = "pymssql-2.2.1-cp37-cp37m-win_amd64.whl", hash = "sha256:42cbfc756c9b29f3b974a3352c744c90c280c905f7cadda2dfcb6e46ca96b3f6"}, + {file = "pymssql-2.2.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:8319bbbcaa8b3ca89f897e808ca5b48d9c64d3231408b1f0e1ce4400bcd7d6ae"}, + {file = "pymssql-2.2.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:dbfc4b97e6e6ce776461570d79c738116c20e2c2c01ed5f3afe03ec6740dacce"}, + {file = "pymssql-2.2.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:c841921a1729035f8fe056c76b1202985f203b4ff589904d26cb33885271cdad"}, + {file = "pymssql-2.2.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:2b865ba3644e08d2ce10e2b06256dadb64677e1c81651224c4b1cabea2be2fd8"}, + {file = "pymssql-2.2.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:4465d1776d3cf36d17b3058d155ec8a581b1bc9ecf29740ea07254ea72248b73"}, + {file = "pymssql-2.2.1-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:0b4c2b4b3b13f866a037c905220c6b3691c20d19a18ff6f6457351f15620db46"}, + {file = "pymssql-2.2.1-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:cead77d3ac65c1e2910c3c082760148fd275815d5df4b13549e485fc305f4768"}, + {file = "pymssql-2.2.1-cp38-cp38-manylinux_2_24_i686.whl", hash = "sha256:c956c93f57d69c4551b442dec2b6eed1e4a0e185ae913ec52305e4b66d4903b7"}, + {file = "pymssql-2.2.1-cp38-cp38-manylinux_2_24_x86_64.whl", hash = "sha256:fd2c537c798d2e0166cdebd2dd29f1a676fc508d664cf1fefe69ae51c3004a82"}, + {file = "pymssql-2.2.1-cp38-cp38-win32.whl", hash = "sha256:a82ba1f66f6537a42c54704d0da171a1541a3d88225d6e9ba6a17712968b0980"}, + {file = "pymssql-2.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:a9adf3ca9f143dace3d4d52bc056e8a70e5f956c4555a9e204ddf4937d98ba66"}, + {file = "pymssql-2.2.1-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:724432260900d1a4dff51da52f276741e143756712fbf285d8b228b2340403a9"}, + {file = "pymssql-2.2.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:0acfb137c385b14a7b27c6e9c6c2a047e5575c45b85239503086895d8d71819e"}, + {file = "pymssql-2.2.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:a67b45a91203a35251d427cd35a316e878a27d275f20a6ae815a0db6bb0769de"}, + {file = "pymssql-2.2.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:844883d3543d8da5037ef8a925a75d0c1de3972d2f9754f063c87c7d7f580b68"}, + {file = "pymssql-2.2.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:d28cec093e53f7a7e6242683f46418a2c0348eb6d22c5008d442028b6207e204"}, + {file = "pymssql-2.2.1-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:fe53b55ef9572ac3d5f34f2acd3adf1ec9ee7d1f637bc59bdd58dc06c4ef4ed7"}, + {file = "pymssql-2.2.1-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:6ef017731bd6e1ffaed4637e767c1983750f8b63de6f8e6ed1e700578a73b4a3"}, + {file = "pymssql-2.2.1-cp39-cp39-manylinux_2_24_i686.whl", hash = "sha256:c788534ff389d31742f71a8fae2922b6a498bcde8e3c6c650f15495f33e50e44"}, + {file = "pymssql-2.2.1-cp39-cp39-manylinux_2_24_x86_64.whl", hash = "sha256:6b845d1c940521d3ec344906208fbc001bef4913e780ae799ad06f4d9e197f8b"}, + {file = "pymssql-2.2.1-cp39-cp39-win32.whl", hash = "sha256:13d0cce2716d34e8486cdd83602f72e13a1261de1f50a98ddf161d207e0f3ec0"}, + {file = "pymssql-2.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:637432b07f9b6e5f0b1d77cec8b32b6d5ee182033c6c7b47ef2d5a3d9233ee4c"}, + {file = "pymssql-2.2.1.tar.gz", hash = "sha256:7238530b45955f793d235664cc6f104d8b8fbcdeb6fa394dd22d8fe43748bab0"}, ] pymysql = [ {file = "PyMySQL-1.0.2-py3-none-any.whl", hash = "sha256:41fc3a0c5013d5f039639442321185532e3e2c8924687abe6537de157d403641"}, @@ -3682,8 +4066,8 @@ pynacl = [ {file = "PyNaCl-1.4.0.tar.gz", hash = "sha256:54e9a2c849c742006516ad56a88f5c74bf2ce92c9f67435187c3c5953b346505"}, ] pyotp = [ - {file = "pyotp-2.4.1-py2.py3-none-any.whl", hash = "sha256:ef07c393660529261e66902e788b32e46260d2c29eb740978df778260a1c2b4c"}, - {file = "pyotp-2.4.1.tar.gz", hash = "sha256:038a3f70b34eaad3f72459e8b411662ef8dfcdd95f7d9203fa489e987a75584b"}, + {file = "pyotp-2.6.0-py2.py3-none-any.whl", hash = "sha256:9d144de0f8a601d6869abe1409f4a3f75f097c37b50a36a3bf165810a6e23f28"}, + {file = "pyotp-2.6.0.tar.gz", hash = "sha256:d28ddfd40e0c1b6a6b9da961c7d47a10261fb58f378cb00f05ce88b26df9c432"}, ] pyparsing = [ {file = "pyparsing-2.1.10-py2.py3-none-any.whl", hash = "sha256:67101d7acee692962f33dd30b5dce079ff532dd9aa99ff48d52a3dad51d2fe84"}, @@ -3702,40 +4086,25 @@ pypdf4 = [ {file = "PyPDF4-1.27.0.tar.gz", hash = "sha256:7c932441146d205572f96254d53c79ea2c30c9e11df55a5cf87e056c7b3d7f89"}, ] pyproj = [ - {file = "pyproj-3.0.0.post1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c5c2f3a42d7ec4315207756fa22d94c2f1d44974a897d95fd0ae50c6275b10f"}, - {file = "pyproj-3.0.0.post1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:4098c6245af35bc08c94d0569e3f4072520735c8fb6d484da26ac12de90d1461"}, - {file = "pyproj-3.0.0.post1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:ff0ab697e710772ace753b6d72f017e013dd9d5aa0878406cc25d02c75c12963"}, - {file = "pyproj-3.0.0.post1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:b845c6fbeae886ae4f06460ee35f9ae8526e5dc92c5db71bc575f0f836e2c11c"}, - {file = "pyproj-3.0.0.post1-cp36-cp36m-win32.whl", hash = "sha256:0e9c7a56ceb3a65d23a99b839ee846817d367c2f3c066b7687e78d9642331b3a"}, - {file = "pyproj-3.0.0.post1-cp36-cp36m-win_amd64.whl", hash = "sha256:57f35a708e10e5f24fec6f02643559bdcfcbeb757d5d1dc03049b818525002d3"}, - {file = "pyproj-3.0.0.post1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cc0bac8f6fb46441f8b472cdad6c4809898c7f90f4f043420eee27e44f49b4e9"}, - {file = "pyproj-3.0.0.post1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:1b09aa6a75c66fc7eaa0b48fadaaa5f831f4621b2c8d4c692cf1f21597200467"}, - {file = "pyproj-3.0.0.post1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6d76793b507341b29ca8d17da76c3f047e936f65728a7a5a549fb8e55b42a21b"}, - {file = "pyproj-3.0.0.post1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:f9bfbadd28d258801853b2ea309f2d37c289a476a7eb08b4212f83627da52d60"}, - {file = "pyproj-3.0.0.post1-cp37-cp37m-win32.whl", hash = "sha256:657df773781d80d122e7d040464c17a004cdd7338739b8b24321ae3dbd872427"}, - {file = "pyproj-3.0.0.post1-cp37-cp37m-win_amd64.whl", hash = "sha256:73d495eca7ba83d9ea32b08cf86f65cbc2292cd2d889a2229bac4a56a32f2d5b"}, - {file = "pyproj-3.0.0.post1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a917e1d22e7a195edb06a7345c65e608b401fceead8dc96c49a00d06ff2f5e12"}, - {file = "pyproj-3.0.0.post1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:1974506d59f3cf57bdb05aabace43ed8dcbb9822373bfc7b4e85b9458ea22007"}, - {file = "pyproj-3.0.0.post1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:c3388bd9b23a5dab4d81331a3e9cde409c9f2bf2ce3f2c125a797000215c0062"}, - {file = "pyproj-3.0.0.post1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:8d3e61c59e624e76d9f26909ff6b50b04d0328ff7431ff7ec123d8b762d51998"}, - {file = "pyproj-3.0.0.post1-cp38-cp38-win32.whl", hash = "sha256:cdd6afc4a96aa69c605cd26d139714f3d0d51f2e50de308a4cfa04d8df9791d4"}, - {file = "pyproj-3.0.0.post1-cp38-cp38-win_amd64.whl", hash = "sha256:5f99e5f9303fcd30ee958a2dc5c50ead33523fc2e3d1b789f244047f7e348d8e"}, - {file = "pyproj-3.0.0.post1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4b49aad9ef82cb9d1768af3381a6691e7d011cacfea7914cab15a029f3d48197"}, - {file = "pyproj-3.0.0.post1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:2efc593fb610654ff002c6e48dde11a430d997c2c7f2e5a26793e93b58a2f137"}, - {file = "pyproj-3.0.0.post1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:608a09a4b739742ebe10a2c6f3d33f1e22a26d7763c1005ebd63cb00169b5112"}, - {file = "pyproj-3.0.0.post1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:1c4002dc1d06f750da80a63528195e0f4c18b466470ee8b3911bfadec0689036"}, - {file = "pyproj-3.0.0.post1-cp39-cp39-win32.whl", hash = "sha256:ab1b3af7ba2d06e45486d80967ad83028a252b15566cc326ae40ed067e0167cc"}, - {file = "pyproj-3.0.0.post1-cp39-cp39-win_amd64.whl", hash = "sha256:839c7c4478073c1e5109674d61edf0450e61e4317aabcd4f12e349be14eeeff9"}, - {file = "pyproj-3.0.0.post1-pp37-pypy37_pp73-win32.whl", hash = "sha256:8ba718f552e69073105021fd7b5ceb2189d4376e66d519c3b4cf0f1aed6a54d3"}, - {file = "pyproj-3.0.0.post1.tar.gz", hash = "sha256:a49581629cadd29e61fc061d153a4d62ff28b4063c71fe8ca881eeb98cd22017"}, -] -pyreadline = [ - {file = "pyreadline-2.1.win-amd64.exe", hash = "sha256:9ce5fa65b8992dfa373bddc5b6e0864ead8f291c94fbfec05fbd5c836162e67b"}, - {file = "pyreadline-2.1.win32.exe", hash = "sha256:65540c21bfe14405a3a77e4c085ecfce88724743a4ead47c66b84defcf82c32e"}, - {file = "pyreadline-2.1.zip", hash = "sha256:4530592fc2e85b25b1a9f79664433da09237c1a270e4d78ea5aa3a2c7229e2d1"}, -] -pyrfc = [ - {file = "pyrfc-0.1.2.tar.gz", hash = "sha256:101ab6ac5c99025caf8d2f1e728dac1650d9b8a8c584120c670bc9ff32977578"}, + {file = "pyproj-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8eda240225971b5cd0bac2d399ed6222068f0598ee92d5f6e847bd2019d2c8b0"}, + {file = "pyproj-3.1.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:ae237492767e0225f99b53a0fd7110fde2b7e7cabc105bbc243c151a7497de88"}, + {file = "pyproj-3.1.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:b635e7e21fea5af74e90fc9e54d1a4c27078efdce6f214101c98dd93afae599a"}, + {file = "pyproj-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa87df0982aa0f4477478899d9c930cc0f97cd6d8a4ce84c43ac88ccf86d1da7"}, + {file = "pyproj-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:10dad599b9f7ce2194996dc25f1000e0aa15754ecef9db46b624713959c67957"}, + {file = "pyproj-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:a162ed199cd2ec392cffe20b2fa3381b68e7a166d55f3f060eceb8d517e4f46d"}, + {file = "pyproj-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1e88ebc4e08e661e9011b5c1ebfb32f0d311963a9824a6effb4168c7e07918b1"}, + {file = "pyproj-3.1.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:da88abc5e2f6a8fb07533855a57ca2a31845f58901a87f821b68b0db6b023978"}, + {file = "pyproj-3.1.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:911d773da9fa4d4f3f7580173858c391e3ee0b61acaf0be303baab323d2eae78"}, + {file = "pyproj-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f8a8d982bde211e65dc2de1f8f36cf162f9cc7fcd8a7625046ea265284e5e65"}, + {file = "pyproj-3.1.0-cp38-cp38-win32.whl", hash = "sha256:c4193e1069d165476b2d0f7d882b7712b3eab6e2e6fe2a0a78ef40de825a1f28"}, + {file = "pyproj-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:b6c74bbec679199746a3e02c0e0fad093c3652df96dd63e086a2fbf2afe9dc0e"}, + {file = "pyproj-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:04c185102e659439c5bd428ac5473d36ef795fca8e225bbbe78e20643d804ec0"}, + {file = "pyproj-3.1.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ebbba7707fe83a01e54bce8e3e7342feb0b3e0d74ff8c28df12f8bc59b76827c"}, + {file = "pyproj-3.1.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9cc464a1c51baad28ffb7a233116e8d4ce4c560b32039fa986d0f992ac3c431f"}, + {file = "pyproj-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f3ad09cf3352bf5664794042b28d98781362ec8d9774ad73f28a1a0101a27f1"}, + {file = "pyproj-3.1.0-cp39-cp39-win32.whl", hash = "sha256:ae5534fa7a3b74f20534694d297fce6f7483890ff6ca404394ecf372f3c589d4"}, + {file = "pyproj-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:808f5992320e9631b2e45444028a65cd6ba3ee40229292934178ef07020a5ffd"}, + {file = "pyproj-3.1.0.tar.gz", hash = "sha256:67b94f4e694ae33fc90dfb7da0e6b5ed5f671dd0acc2f6cf46e9c39d56e16e1a"}, ] pyrsistent = [ {file = "pyrsistent-0.16.0.tar.gz", hash = "sha256:28669905fe725965daa16184933676547c5bb40a5153055a8dee2a4bd7933ad3"}, @@ -3773,11 +4142,12 @@ python-keystoneclient = [ {file = "python_keystoneclient-3.22.0-py2.py3-none-any.whl", hash = "sha256:b9f9e74219a44be7c9955c836ab9a7ae16bde7325db6db15b6e5fe140c11bc3a"}, ] python-slugify = [ - {file = "python-slugify-4.0.1.tar.gz", hash = "sha256:69a517766e00c1268e5bbfc0d010a0a8508de0b18d30ad5a1ff357f8ae724270"}, + {file = "python-slugify-5.0.2.tar.gz", hash = "sha256:f13383a0b9fcbe649a1892b9c8eb4f8eab1d6d84b84bb7a624317afa98159cab"}, + {file = "python_slugify-5.0.2-py2.py3-none-any.whl", hash = "sha256:6d8c5df75cd4a7c3a2d21e257633de53f52ab0265cd2d1dc62a730e8194a7380"}, ] python-stdnum = [ - {file = "python-stdnum-1.15.tar.gz", hash = "sha256:ff0e4d2b8731711cf2a73d22964139208088b4bd1a3e3b0c4f78d6e823dd8923"}, - {file = "python_stdnum-1.15-py2.py3-none-any.whl", hash = "sha256:46c05dff2d5ff89b12cc63ab54cca1e4788e4e3087c163a1b7434a53fa926f28"}, + {file = "python-stdnum-1.16.tar.gz", hash = "sha256:4248d898042a801fc4eff96fbfe4bf63a43324854efe3b5534718c1c195c6f43"}, + {file = "python_stdnum-1.16-py2.py3-none-any.whl", hash = "sha256:2e2c56c548ca166b95547a8d748f4d71320a5b4896960717c8e6380e08d993a5"}, ] python-swiftclient = [ {file = "python-swiftclient-3.9.0.tar.gz", hash = "sha256:4f2097492e4c76e948882fc859bfa033ade09bed72f8e6b328e34a3467d9a377"}, @@ -3871,8 +4241,8 @@ requests-file = [ {file = "requests_file-1.5.1-py2.py3-none-any.whl", hash = "sha256:dfe5dae75c12481f68ba353183c53a65e6044c923e64c24b2209f6c7570ca953"}, ] requests-mock = [ - {file = "requests-mock-1.8.0.tar.gz", hash = "sha256:e68f46844e4cee9d447150343c9ae875f99fa8037c6dcf5f15bf1fe9ab43d226"}, - {file = "requests_mock-1.8.0-py2.py3-none-any.whl", hash = "sha256:11215c6f4df72702aa357f205cf1e537cffd7392b3e787b58239bde5fb3db53b"}, + {file = "requests-mock-1.9.3.tar.gz", hash = "sha256:8d72abe54546c1fc9696fa1516672f1031d72a55a1d66c85184f972a24ba0eba"}, + {file = "requests_mock-1.9.3-py2.py3-none-any.whl", hash = "sha256:0a2d38a117c08bb78939ec163522976ad59a6b7fdd82b709e23bb98004a44970"}, ] requests-oauthlib = [ {file = "requests-oauthlib-1.1.0.tar.gz", hash = "sha256:eabd8eb700ebed81ba080c6ead96d39d6bdc39996094bd23000204f6965786b0"}, @@ -3883,6 +4253,9 @@ requests-toolbelt = [ {file = "requests-toolbelt-0.9.1.tar.gz", hash = "sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0"}, {file = "requests_toolbelt-0.9.1-py2.py3-none-any.whl", hash = "sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f"}, ] +restructuredtext-lint = [ + {file = "restructuredtext_lint-1.3.1.tar.gz", hash = "sha256:470e53b64817211a42805c3a104d2216f6f5834b22fe7adb637d1de4d6501fb8"}, +] retrying = [ {file = "retrying-1.3.3.tar.gz", hash = "sha256:08c039560a6da2fe4f2c426d0766e284d3b736e355f8dd24b37367b0bb41973b"}, ] @@ -3890,13 +4263,6 @@ rfc3986 = [ {file = "rfc3986-1.4.0-py2.py3-none-any.whl", hash = "sha256:af9147e9aceda37c91a05f4deb128d4b4b49d6b199775fd2d2927768abdc8f50"}, {file = "rfc3986-1.4.0.tar.gz", hash = "sha256:112398da31a3344dc25dbf477d8df6cb34f9278a94fee2625d89e4514be8bb9d"}, ] -rotate-backups = [ - {file = "rotate-backups-4.3.tar.gz", hash = "sha256:8824f97f3e928f46728749669b039d994e88cd7c583ebb7f83f4325b892ab794"}, - {file = "rotate_backups-4.3-py2.py3-none-any.whl", hash = "sha256:c71170fa2c5cb40214cb63cef37cc3b696582f6676918517eec97654ea858a20"}, -] -rotate-backups-s3 = [ - {file = "rotate-backups-s3-0.3.tar.gz", hash = "sha256:b5be4294a82d9b8619a60d17feca41142c617510fc13ea2e9ba2800c347d02ef"}, -] s3transfer = [ {file = "s3transfer-0.2.1-py2.py3-none-any.whl", hash = "sha256:b780f2411b824cb541dbcd2c713d0cb61c7d1bcadae204cdddda2b35cef493ba"}, {file = "s3transfer-0.2.1.tar.gz", hash = "sha256:6efc926738a3cd576c2a79725fed9afde92378aa5c6a957e3af010cb019fac9d"}, @@ -3926,9 +4292,6 @@ shapely = [ {file = "Shapely-1.6.4.post2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:3ef28e3f20a1c37f5b99ea8cf8dcb58e2f1a8762d65ed2d21fd92bf1d4811182"}, {file = "Shapely-1.6.4.post2.tar.gz", hash = "sha256:c4b87bb61fc3de59fc1f85e71a79b0c709dc68364d9584473697aad4aa13240f"}, ] -simpleeval = [ - {file = "simpleeval-0.9.10.tar.gz", hash = "sha256:692055488c2864637f6c2edb5fa48175978a2a07318009e7cf03c9790ca17bea"}, -] simplejson = [ {file = "simplejson-3.17.2-cp27-cp27m-macosx_10_13_x86_64.whl", hash = "sha256:2d3eab2c3fe52007d703a26f71cf649a8c771fcdd949a3ae73041ba6797cfcf8"}, {file = "simplejson-3.17.2-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:813846738277729d7db71b82176204abc7fdae2f566e2d9fcf874f9b6472e3e6"}, @@ -3980,6 +4343,9 @@ six = [ {file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"}, {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, ] +slimit = [ + {file = "slimit-0.8.1.zip", hash = "sha256:f433dcef899f166b207b67d91d3f7344659cb33b8259818f084167244e17720b"}, +] slugify = [ {file = "slugify-0.0.1.tar.gz", hash = "sha256:c5703cc11c1a6947536f3ce8bb306766b8bb5a84a53717f5a703ce0f18235e4c"}, ] @@ -3999,8 +4365,8 @@ soupsieve = [ {file = "soupsieve-1.9.6.tar.gz", hash = "sha256:7985bacc98c34923a439967c1a602dc4f1e15f923b6fcf02344184f86cc7efaa"}, ] sphinx = [ - {file = "Sphinx-3.4.3-py3-none-any.whl", hash = "sha256:c314c857e7cd47c856d2c5adff514ac2e6495f8b8e0f886a8a37e9305dfea0d8"}, - {file = "Sphinx-3.4.3.tar.gz", hash = "sha256:41cad293f954f7d37f803d97eb184158cfd90f51195131e94875bc07cd08b93c"}, + {file = "Sphinx-4.0.2-py3-none-any.whl", hash = "sha256:d1cb10bee9c4231f1700ec2e24a91be3f3a3aba066ea4ca9f3bbe47e59d5a1d4"}, + {file = "Sphinx-4.0.2.tar.gz", hash = "sha256:b5c2ae4120bf00c799ba9b3699bc895816d272d120080fbc967292f29b52b48c"}, ] sphinx-intl = [ {file = "sphinx-intl-2.0.1.tar.gz", hash = "sha256:b25a6ec169347909e8d983eefe2d8adecb3edc2f27760db79b965c69950638b4"}, @@ -4010,8 +4376,8 @@ sphinx-patchqueue = [ {file = "sphinx-patchqueue-1.0.4.tar.gz", hash = "sha256:00362a5985c79eb038ab4a564f9944cfd097bd94350caab4fdebaabfb9eb3bd3"}, ] sphinx-rtd-theme = [ - {file = "sphinx_rtd_theme-0.5.1-py2.py3-none-any.whl", hash = "sha256:fa6bebd5ab9a73da8e102509a86f3fcc36dec04a0b52ea80e5a033b2aba00113"}, - {file = "sphinx_rtd_theme-0.5.1.tar.gz", hash = "sha256:eda689eda0c7301a80cf122dad28b1861e5605cbf455558f3775e1e8200e83a5"}, + {file = "sphinx_rtd_theme-0.5.2-py2.py3-none-any.whl", hash = "sha256:4a05bdbe8b1446d77a01e20a23ebc6777c74f43237035e76be89699308987d6f"}, + {file = "sphinx_rtd_theme-0.5.2.tar.gz", hash = "sha256:32bd3b5d13dc8186d7a42fc816a23d32e83a4827d7d9882948e7b837c232da5a"}, ] sphinxcontrib-applehelp = [ {file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"}, @@ -4038,44 +4404,36 @@ sphinxcontrib-serializinghtml = [ {file = "sphinxcontrib_serializinghtml-1.1.4-py2.py3-none-any.whl", hash = "sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a"}, ] sqlalchemy = [ - {file = "SQLAlchemy-1.3.22-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:61628715931f4962e0cdb2a7c87ff39eea320d2aa96bd471a3c293d146f90394"}, - {file = "SQLAlchemy-1.3.22-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:81d8d099a49f83111cce55ec03cc87eef45eec0d90f9842b4fc674f860b857b0"}, - {file = "SQLAlchemy-1.3.22-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:d055ff750fcab69ca4e57b656d9c6ad33682e9b8d564f2fbe667ab95c63591b0"}, - {file = "SQLAlchemy-1.3.22-cp27-cp27m-win32.whl", hash = "sha256:9bf572e4f5aa23f88dd902f10bb103cb5979022a38eec684bfa6d61851173fec"}, - {file = "SQLAlchemy-1.3.22-cp27-cp27m-win_amd64.whl", hash = "sha256:7d4b8de6bb0bc736161cb0bbd95366b11b3eb24dd6b814a143d8375e75af9990"}, - {file = "SQLAlchemy-1.3.22-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:4a84c7c7658dd22a33dab2e2aa2d17c18cb004a42388246f2e87cb4085ef2811"}, - {file = "SQLAlchemy-1.3.22-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:f1e88b30da8163215eab643962ae9d9252e47b4ea53404f2c4f10f24e70ddc62"}, - {file = "SQLAlchemy-1.3.22-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:f115150cc4361dd46153302a640c7fa1804ac207f9cc356228248e351a8b4676"}, - {file = "SQLAlchemy-1.3.22-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6aaa13ee40c4552d5f3a59f543f0db6e31712cc4009ec7385407be4627259d41"}, - {file = "SQLAlchemy-1.3.22-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:3ab5b44a07b8c562c6dcb7433c6a6c6e03266d19d64f87b3333eda34e3b9936b"}, - {file = "SQLAlchemy-1.3.22-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:426ece890153ccc52cc5151a1a0ed540a5a7825414139bb4c95a868d8da54a52"}, - {file = "SQLAlchemy-1.3.22-cp35-cp35m-win32.whl", hash = "sha256:bd4b1af45fd322dcd1fb2a9195b4f93f570d1a5902a842e3e6051385fac88f9c"}, - {file = "SQLAlchemy-1.3.22-cp35-cp35m-win_amd64.whl", hash = "sha256:62285607a5264d1f91590abd874d6a498e229d5840669bd7d9f654cfaa599bd0"}, - {file = "SQLAlchemy-1.3.22-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:314f5042c0b047438e19401d5f29757a511cfc2f0c40d28047ca0e4c95eabb5b"}, - {file = "SQLAlchemy-1.3.22-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:62fb881ba51dbacba9af9b779211cf9acff3442d4f2993142015b22b3cd1f92a"}, - {file = "SQLAlchemy-1.3.22-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:bde677047305fe76c7ee3e4492b545e0018918e44141cc154fe39e124e433991"}, - {file = "SQLAlchemy-1.3.22-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:0c6406a78a714a540d980a680b86654feadb81c8d0eecb59f3d6c554a4c69f19"}, - {file = "SQLAlchemy-1.3.22-cp36-cp36m-win32.whl", hash = "sha256:95bde07d19c146d608bccb9b16e144ec8f139bcfe7fd72331858698a71c9b4f5"}, - {file = "SQLAlchemy-1.3.22-cp36-cp36m-win_amd64.whl", hash = "sha256:888d5b4b5aeed0d3449de93ea80173653e939e916cc95fe8527079e50235c1d2"}, - {file = "SQLAlchemy-1.3.22-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:d53f59744b01f1440a1b0973ed2c3a7de204135c593299ee997828aad5191693"}, - {file = "SQLAlchemy-1.3.22-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:70121f0ae48b25ef3e56e477b88cd0b0af0e1f3a53b5554071aa6a93ef378a03"}, - {file = "SQLAlchemy-1.3.22-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:54da615e5b92c339e339fe8536cce99fe823b6ed505d4ea344852aefa1c205fb"}, - {file = "SQLAlchemy-1.3.22-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:68428818cf80c60dc04aa0f38da20ad39b28aba4d4d199f949e7d6e04444ea86"}, - {file = "SQLAlchemy-1.3.22-cp37-cp37m-win32.whl", hash = "sha256:17610d573e698bf395afbbff946544fbce7c5f4ee77b5bcb1f821b36345fae7a"}, - {file = "SQLAlchemy-1.3.22-cp37-cp37m-win_amd64.whl", hash = "sha256:216ba5b4299c95ed179b58f298bda885a476b16288ab7243e89f29f6aeced7e0"}, - {file = "SQLAlchemy-1.3.22-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:0c72b90988be749e04eff0342dcc98c18a14461eb4b2ad59d611b57b31120f90"}, - {file = "SQLAlchemy-1.3.22-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:491fe48adc07d13e020a8b07ef82eefc227003a046809c121bea81d3dbf1832d"}, - {file = "SQLAlchemy-1.3.22-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:f8191fef303025879e6c3548ecd8a95aafc0728c764ab72ec51a0bdf0c91a341"}, - {file = "SQLAlchemy-1.3.22-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:108580808803c7732f34798eb4a329d45b04c562ed83ee90f09f6a184a42b766"}, - {file = "SQLAlchemy-1.3.22-cp38-cp38-win32.whl", hash = "sha256:bab5a1e15b9466a25c96cda19139f3beb3e669794373b9ce28c4cf158c6e841d"}, - {file = "SQLAlchemy-1.3.22-cp38-cp38-win_amd64.whl", hash = "sha256:318b5b727e00662e5fc4b4cd2bf58a5116d7c1b4dd56ffaa7d68f43458a8d1ed"}, - {file = "SQLAlchemy-1.3.22-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:1418f5e71d6081aa1095a1d6b567a562d2761996710bdce9b6e6ba20a03d0864"}, - {file = "SQLAlchemy-1.3.22-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:5a7f224cdb7233182cec2a45d4c633951268d6a9bcedac37abbf79dd07012aea"}, - {file = "SQLAlchemy-1.3.22-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:715b34578cc740b743361f7c3e5f584b04b0f1344f45afc4e87fbac4802eb0a0"}, - {file = "SQLAlchemy-1.3.22-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:2ff132a379838b1abf83c065be54cef32b47c987aedd06b82fc76476c85225eb"}, - {file = "SQLAlchemy-1.3.22-cp39-cp39-win32.whl", hash = "sha256:c389d7cc2b821853fb018c85457da3e7941db64f4387720a329bc7ff06a27963"}, - {file = "SQLAlchemy-1.3.22-cp39-cp39-win_amd64.whl", hash = "sha256:04f995fcbf54e46cddeb4f75ce9dfc17075d6ae04ac23b2bacb44b3bc6f6bf11"}, - {file = "SQLAlchemy-1.3.22.tar.gz", hash = "sha256:758fc8c4d6c0336e617f9f6919f9daea3ab6bb9b07005eda9a1a682e24a6cacc"}, + {file = "SQLAlchemy-1.4.19-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:ddbce8fe4d0190db21db602e38aaf4c158c540b49f1ef7475323ec682a9fbf2d"}, + {file = "SQLAlchemy-1.4.19-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:942ca49b7ec7449d2473a6587825c55ad99534ddfc4eee249dd42be3cc1aa8c9"}, + {file = "SQLAlchemy-1.4.19-cp27-cp27m-win32.whl", hash = "sha256:9c0945c79cbe507b49524e31a4bb8700060bbccb60bb553df6432e176baff3d5"}, + {file = "SQLAlchemy-1.4.19-cp27-cp27m-win_amd64.whl", hash = "sha256:6fd1b745ade2020a1a7bf1e22536d8afe86287882c81ca5d860bdf231d5854e9"}, + {file = "SQLAlchemy-1.4.19-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:0fb3f73e5009f5a4c9b24469939d3d57cc3ad8099a09c0cfefc47fe45ab7ffbe"}, + {file = "SQLAlchemy-1.4.19-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:64eab458619ef759f16f0f82242813d3289e829f8557fbc7c212ca4eadf96472"}, + {file = "SQLAlchemy-1.4.19-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:311051c06f905774427b4a92dcb3924d6ee563dea3a88176da02fdfc572d0d1d"}, + {file = "SQLAlchemy-1.4.19-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a34a7fd3353ee61a1dca72fc0c3e38d4e56bdc2c343e712f60a8c70acd4ef5bf"}, + {file = "SQLAlchemy-1.4.19-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ace9ab2af9d7d7b0e2ff2178809941c56ab8921e38128278192a73a8a1c08a2"}, + {file = "SQLAlchemy-1.4.19-cp36-cp36m-win32.whl", hash = "sha256:96d3d4a7ead376d738775a1fa9786dc17a31975ec664cea284e53735c79a5686"}, + {file = "SQLAlchemy-1.4.19-cp36-cp36m-win_amd64.whl", hash = "sha256:20f4bf1459548a74aade997cb045015e4d72f0fde1789b09b3bb380be28f6511"}, + {file = "SQLAlchemy-1.4.19-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:8cba69545246d16c6d2a12ce45865947cbdd814bacddf2e532fdd4512e70728c"}, + {file = "SQLAlchemy-1.4.19-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57ba8a96b6d058c7dcf44de8ac0955b7a787f7177a0221dd4b8016e0191268f5"}, + {file = "SQLAlchemy-1.4.19-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8f1e7f4de05c15d6b46af12f3cf0c2552f2940d201a49926703249a62402d851"}, + {file = "SQLAlchemy-1.4.19-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c92d9ebf4b38c22c0c9e4f203a80e101910a50dc555b4578816932015b97d7f"}, + {file = "SQLAlchemy-1.4.19-cp37-cp37m-win32.whl", hash = "sha256:c6efc7477551ba9ce632d5c3b448b7de0277c86005eec190a1068fcc7115fd0e"}, + {file = "SQLAlchemy-1.4.19-cp37-cp37m-win_amd64.whl", hash = "sha256:e2761b925fda550debfd5a8bc3cef9debc9a23c6a280429c4ec3a07c35c6b4b3"}, + {file = "SQLAlchemy-1.4.19-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:58d4f79d119010fdced6e7fd7e4b9f2230dbf55a8235d7c58b1c8207ef74791b"}, + {file = "SQLAlchemy-1.4.19-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cefd44faca7c57534503261f6fab49bd47eb9c2945ee0bab09faaa8cb047c24f"}, + {file = "SQLAlchemy-1.4.19-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9133635edcec1e7fbfc16eba5dc2b5b3b11818d25b7a57cfcbfa8d3b3e9594fd"}, + {file = "SQLAlchemy-1.4.19-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3cf5f543d048a7c8da500133068c5c90c97a2c4bf0c027928a85028a519f33d"}, + {file = "SQLAlchemy-1.4.19-cp38-cp38-win32.whl", hash = "sha256:d04160462f874eaa4d88721a0d5ecca8ebf433616801efe779f252ef87b0e216"}, + {file = "SQLAlchemy-1.4.19-cp38-cp38-win_amd64.whl", hash = "sha256:45b0f773e195d8d51e2fd67cb5b5fb32f5a1f5e7f0752016207091bed108909a"}, + {file = "SQLAlchemy-1.4.19-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:93ba458b3c279581288a10a55df2aa6ac3509882228fcbad9d9d88069f899337"}, + {file = "SQLAlchemy-1.4.19-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6317701c06a829b066c794545512bb70b1a10a74574cfa5658a0aaf49f31aa93"}, + {file = "SQLAlchemy-1.4.19-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:95a9fd0a11f89a80d8815418eccba034f3fec8ea1f04c41b6b8decc5c95852e9"}, + {file = "SQLAlchemy-1.4.19-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9014fd1d8aebcb4eb6bc69a382dd149200e1d5924412b1d08b4443f6c1ce526f"}, + {file = "SQLAlchemy-1.4.19-cp39-cp39-win32.whl", hash = "sha256:fa05a77662c23226c9ec031638fd90ae767009e05cd092b948740f09d10645f0"}, + {file = "SQLAlchemy-1.4.19-cp39-cp39-win_amd64.whl", hash = "sha256:d7b21a4b62921cf6dca97e8f9dea1fbe2432aebbb09895a2bd4f527105af41a4"}, + {file = "SQLAlchemy-1.4.19.tar.gz", hash = "sha256:89a5a13dcf33b7e47c7a9404a297c836965a247c7f076a0fe0910cae2bee5ce2"}, ] statsd = [ {file = "statsd-3.2.1-py2.py3-none-any.whl", hash = "sha256:7aff40c6cdda703193fac6231410c6c0ad5939ce053a168016501e982c755c84"}, @@ -4093,6 +4451,10 @@ text-unidecode = [ {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"}, {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, ] +tinycss2 = [ + {file = "tinycss2-1.1.0-py3-none-any.whl", hash = "sha256:0353b5234bcaee7b1ac7ca3dea7e02cd338a9f8dcbb8f2dcd32a5795ec1e5f9a"}, + {file = "tinycss2-1.1.0.tar.gz", hash = "sha256:fbdcac3044d60eb85fdb2aa840ece43cf7dbe798e373e6ee0be545d4d134e18a"}, +] toml = [ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, @@ -4115,6 +4477,38 @@ twython = [ {file = "twython-3.8.2-py3-none-any.whl", hash = "sha256:a469d673fdd20d1c346e9b9f784212db521aa611bbdfc4912229ab701b36002b"}, {file = "twython-3.8.2.tar.gz", hash = "sha256:c6ca64309260e0ab47267f76217c80812f591991437f376fc61498816384f9e7"}, ] +typed-ast = [ + {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6"}, + {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c907f561b1e83e93fad565bac5ba9c22d96a54e7ea0267c708bffe863cbe4075"}, + {file = "typed_ast-1.4.3-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:1b3ead4a96c9101bef08f9f7d1217c096f31667617b58de957f690c92378b528"}, + {file = "typed_ast-1.4.3-cp35-cp35m-win32.whl", hash = "sha256:dde816ca9dac1d9c01dd504ea5967821606f02e510438120091b84e852367428"}, + {file = "typed_ast-1.4.3-cp35-cp35m-win_amd64.whl", hash = "sha256:777a26c84bea6cd934422ac2e3b78863a37017618b6e5c08f92ef69853e765d3"}, + {file = "typed_ast-1.4.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f8afcf15cc511ada719a88e013cec87c11aff7b91f019295eb4530f96fe5ef2f"}, + {file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:52b1eb8c83f178ab787f3a4283f68258525f8d70f778a2f6dd54d3b5e5fb4341"}, + {file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:01ae5f73431d21eead5015997ab41afa53aa1fbe252f9da060be5dad2c730ace"}, + {file = "typed_ast-1.4.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c190f0899e9f9f8b6b7863debfb739abcb21a5c054f911ca3596d12b8a4c4c7f"}, + {file = "typed_ast-1.4.3-cp36-cp36m-win32.whl", hash = "sha256:398e44cd480f4d2b7ee8d98385ca104e35c81525dd98c519acff1b79bdaac363"}, + {file = "typed_ast-1.4.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bff6ad71c81b3bba8fa35f0f1921fb24ff4476235a6e94a26ada2e54370e6da7"}, + {file = "typed_ast-1.4.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0fb71b8c643187d7492c1f8352f2c15b4c4af3f6338f21681d3681b3dc31a266"}, + {file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:760ad187b1041a154f0e4d0f6aae3e40fdb51d6de16e5c99aedadd9246450e9e"}, + {file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5feca99c17af94057417d744607b82dd0a664fd5e4ca98061480fd8b14b18d04"}, + {file = "typed_ast-1.4.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:95431a26309a21874005845c21118c83991c63ea800dd44843e42a916aec5899"}, + {file = "typed_ast-1.4.3-cp37-cp37m-win32.whl", hash = "sha256:aee0c1256be6c07bd3e1263ff920c325b59849dc95392a05f258bb9b259cf39c"}, + {file = "typed_ast-1.4.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9ad2c92ec681e02baf81fdfa056fe0d818645efa9af1f1cd5fd6f1bd2bdfd805"}, + {file = "typed_ast-1.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b36b4f3920103a25e1d5d024d155c504080959582b928e91cb608a65c3a49e1a"}, + {file = "typed_ast-1.4.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:067a74454df670dcaa4e59349a2e5c81e567d8d65458d480a5b3dfecec08c5ff"}, + {file = "typed_ast-1.4.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7538e495704e2ccda9b234b82423a4038f324f3a10c43bc088a1636180f11a41"}, + {file = "typed_ast-1.4.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:af3d4a73793725138d6b334d9d247ce7e5f084d96284ed23f22ee626a7b88e39"}, + {file = "typed_ast-1.4.3-cp38-cp38-win32.whl", hash = "sha256:f2362f3cb0f3172c42938946dbc5b7843c2a28aec307c49100c8b38764eb6927"}, + {file = "typed_ast-1.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:dd4a21253f42b8d2b48410cb31fe501d32f8b9fbeb1f55063ad102fe9c425e40"}, + {file = "typed_ast-1.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f328adcfebed9f11301eaedfa48e15bdece9b519fb27e6a8c01aa52a17ec31b3"}, + {file = "typed_ast-1.4.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:2c726c276d09fc5c414693a2de063f521052d9ea7c240ce553316f70656c84d4"}, + {file = "typed_ast-1.4.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:cae53c389825d3b46fb37538441f75d6aecc4174f615d048321b716df2757fb0"}, + {file = "typed_ast-1.4.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b9574c6f03f685070d859e75c7f9eeca02d6933273b5e69572e5ff9d5e3931c3"}, + {file = "typed_ast-1.4.3-cp39-cp39-win32.whl", hash = "sha256:209596a4ec71d990d71d5e0d312ac935d86930e6eecff6ccc7007fe54d703808"}, + {file = "typed_ast-1.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:9c6d1a54552b5330bc657b7ef0eae25d00ba7ffe85d9ea8ae6540d2197a3788c"}, + {file = "typed_ast-1.4.3.tar.gz", hash = "sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65"}, +] typing-extensions = [ {file = "typing_extensions-3.7.4.2-py2-none-any.whl", hash = "sha256:f8d2bd89d25bc39dabe7d23df520442fa1d8969b82544370e03d88b5a591c392"}, {file = "typing_extensions-3.7.4.2-py3-none-any.whl", hash = "sha256:6e95524d8a547a91e08f404ae485bbb71962de46967e1b71a0cb89af24e761c5"}, @@ -4147,10 +4541,6 @@ vcrpy-unittest = [ {file = "vcrpy-unittest-0.1.7.tar.gz", hash = "sha256:a508d8848e678243f1c0d4b152a645c18403a8da517b8a44dfcfc35a675ec981"}, {file = "vcrpy_unittest-0.1.7-py2.py3-none-any.whl", hash = "sha256:b5e2d78bf4c13bc04dca04061dda934abba5f2c9d5201f148747800ff80a762b"}, ] -verboselogs = [ - {file = "verboselogs-1.7-py2.py3-none-any.whl", hash = "sha256:d63f23bf568295b95d3530c6864a0b580cec70e7ff974177dead1e4ffbc6ff49"}, - {file = "verboselogs-1.7.tar.gz", hash = "sha256:e33ddedcdfdafcb3a174701150430b11b46ceb64c2a9a26198c76a156568e427"}, -] viivakoodi = [ {file = "viivakoodi-0.8.0.tar.gz", hash = "sha256:670a35774559b25abdb089d58fb8e67e4ee9618f385b8418e5027ab860290e39"}, ] @@ -4165,22 +4555,33 @@ webcolors = [ {file = "webcolors-1.10-py2.py3-none-any.whl", hash = "sha256:2559b4f4694bfcd61c87ee06acad921bd2fdbf0c844bee65fc844c6910c413dd"}, {file = "webcolors-1.10.tar.gz", hash = "sha256:7b11194c414dcf4b9bd8fb5ceaafc9da183b27430883c62f620589eb79b91b6e"}, ] +webencodings = [ + {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, + {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, +] websocket-client = [ - {file = "websocket_client-0.57.0-py2.py3-none-any.whl", hash = "sha256:0fc45c961324d79c781bab301359d5a1b00b13ad1b10415a4780229ef71a5549"}, - {file = "websocket_client-0.57.0.tar.gz", hash = "sha256:d735b91d6d1692a6a181f2a8c9e0238e5f6373356f561bb9dc4c7af36f452010"}, + {file = "websocket-client-1.1.0.tar.gz", hash = "sha256:b68e4959d704768fa20e35c9d508c8dc2bbc041fd8d267c0d7345cffe2824568"}, + {file = "websocket_client-1.1.0-py2.py3-none-any.whl", hash = "sha256:e5c333bfa9fa739538b652b6f8c8fc2559f1d364243c8a689d7c0e1d41c2e611"}, ] wechatpy = [ - {file = "wechatpy-1.8.14-py2.py3-none-any.whl", hash = "sha256:37ec2d46decedbb2a2174f9f7d620c3b5cec53a5185bad01257ff718ac7a6907"}, - {file = "wechatpy-1.8.14.tar.gz", hash = "sha256:5d26c2da51747bcefa3cee11f4c140d1ffe5cfff26fbbf92742be89b30b92141"}, + {file = "wechatpy-1.8.15-py2.py3-none-any.whl", hash = "sha256:0ac7bd23725cc6cbcfcc45cc4864c2afb9e9b630a2fa6763b0fbed9fe714d5f6"}, + {file = "wechatpy-1.8.15.tar.gz", hash = "sha256:0724347ea9ede4f14b59acefd6e41c9baae25e822df204ece3eeba3d9e1dfd03"}, ] werkzeug = [ {file = "Werkzeug-0.11.15-py2.py3-none-any.whl", hash = "sha256:c6f6f89124df0514d886782c658c3e12f2caaa94da34cee3fd82eebf4ebf052b"}, {file = "Werkzeug-0.11.15.tar.gz", hash = "sha256:455d7798ac263266dbd38d4841f7534dd35ca9c3da4a8df303f8488f38f3bcc0"}, ] +wget = [ + {file = "wget-3.2.zip", hash = "sha256:35e630eca2aa50ce998b9b1a127bb26b30dfee573702782aa982f875e3f16061"}, +] wheel = [ {file = "wheel-0.36.2-py2.py3-none-any.whl", hash = "sha256:78b5b185f0e5763c26ca1e324373aadd49182ca90e825f7853f4b2509215dc0e"}, {file = "wheel-0.36.2.tar.gz", hash = "sha256:e11eefd162658ea59a60a0f6c7d493a7190ea4b9a85e335b33489d9f17e0245e"}, ] +whichcraft = [ + {file = "whichcraft-0.6.1-py2.py3-none-any.whl", hash = "sha256:deda9266fbb22b8c64fd3ee45c050d61139cd87419765f588e37c8d23e236dd9"}, + {file = "whichcraft-0.6.1.tar.gz", hash = "sha256:acdbb91b63d6a15efbd6430d1d7b2d36e44a71697e93e19b7ded477afd9fce87"}, +] wrapt = [ {file = "wrapt-1.12.1.tar.gz", hash = "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"}, ] @@ -4200,6 +4601,9 @@ xlwt = [ {file = "xlwt-1.3.0-py2.py3-none-any.whl", hash = "sha256:a082260524678ba48a297d922cc385f58278b8aa68741596a87de01a9c628b2e"}, {file = "xlwt-1.3.0.tar.gz", hash = "sha256:c59912717a9b28f1a3c2a98fd60741014b06b043936dcecbc113eaaada156c88"}, ] +xmlformatter = [ + {file = "xmlformatter-0.2.2.tar.gz", hash = "sha256:3135aaf08ecc33b0efedbe61be8b58fc5e5a878c2d342f6fb1d6fd5e2b60d545"}, +] xmltodict = [ {file = "xmltodict-0.12.0-py2.py3-none-any.whl", hash = "sha256:8bbcb45cc982f48b2ca8fe7e7827c5d792f217ecf1792626f808bf41c3b86051"}, {file = "xmltodict-0.12.0.tar.gz", hash = "sha256:50d8c638ed7ecb88d90561beedbf720c9b4e851a9fa6c47ebd64e99d166d8a21"}, diff --git a/pyproject.toml b/pyproject.toml index 12b840b..8072ce1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,8 @@ authors = [ "Mathieu Benoit ",] python = "^3.7.7" Asterisk = "^0.0.8" Babel = "2.3.4" -GitPython = "^3.1.12" +BeautifulSoup4 = "^4.9.3" +GitPython = "3.1.12" Jinja2 = "2.10.1" Mako = "1.0.4" MarkupSafe = "0.23" @@ -28,37 +29,42 @@ Werkzeug = "0.11.15" XlsxWriter = "0.9.3" agithub = "^2.2.2" altair = "^4.1.0" -argcomplete = "^1.12.2" +argcomplete = "^1.12.3" bokeh = "1.1.0" -boto = "^2.49.0" boto3 = "1.9.102" cachetools = ">=2.0.1" -cerberus = "^1.3.2" +cerberus = "^1.3.4" chardet = "3.0.4" +click = "^8.0.1" +cloudflare = "^2.8.15" code_writer = "^1.1.1" colorama = "^0.4.4" cryptography = "2.6.1" -cython = "^0.29.21" +css-html-prettify = "^2.5.5" +cython = "^0.29.23" ddt = "1.2.0" decorator = "4.0.10" -docutils = "0.12" +docutils = "0.16" ebaysdk = "2.1.5" -email_validator = "^1.1.2" -escpos = "^1.8" -extract-msg = "^0.28.0" -extract_msg = "^0.28.0" -factur-x = "^1.12" +email_validator = "^1.1.3" +emoji = "^1.2.0" +escpos = "^1.9" +extract-msg = "^0.28.7" +extract_msg = "^0.28.7" +factur-x = "^2.3" feedparser = "5.2.1" +flake8 = "^3.9.2" freezegun = "0.3.11" geojson = "2.4.1" gevent = "1.3.4" -gitpython = "^3.1.12" giturlparse = "^0.10.0" greenlet = "0.4.13" html2text = "2016.9.19" -invoice2data = "^0.3.5" +html5print = "^0.1.2" +invoice2data = "^0.3.6" iscompatible = "^0.1.1" jira = "2.0.0" +js2py = "^0.71" keystoneauth1 = "3.14.0" lasso = "^0.0.5" libsass = "0.12.3" @@ -68,20 +74,21 @@ mock = "2.0.0" mpld3 = "0.3" mysqlclient = "^2.0.3" num2words = "0.5.6" -numpy = "^1.19.5" +numpy = "^1.21.0" oauthlib = "2.1.0" "oca.decorators" = "^0.0.1" ofxparse = "0.16" -openpyxl = "^3.0.5" +openpyxl = "^3.0.7" openupgradelib = "^2.0.0" pandas = "1.2.0" paramiko = "^2.7.2" passlib = "1.6.5" -pdf2image = "^1.14.0" +pdf2image = "^1.16.0" +pdfminer = "^20191125" pexpect = "^4.8.0" -phonenumbers = "^8.12.15" +phonenumbers = "^8.12.26" plotly = "4.1.0" -premailer = "^3.7.0" +premailer = "^3.9.0" psutil = "4.3.1" psycopg2 = "2.7.3.1" py-Asterisk = "^0.5.18" @@ -91,11 +98,11 @@ pycountry = "^20.7.3" pydot = "1.2.3" pygount = "<1.2.0" pyldap = "2.4.28" -pymssql = "^2.1.5" +pymssql = "^2.2.1" pymysql = "^1.0.2" -pyotp = "^2.4.1" +pyotp = "^2.6.0" pyparsing = "2.1.10" -pyproj = "^3.0.0" +pyproj = "^3.1.0" pyserial = "3.1.1" pysftp = "^0.2.9" python-chess = "<0.24" @@ -105,7 +112,7 @@ python-git = "^2018.2.1" python-json-logger = "0.1.5" python-keystoneclient = "3.22.0" python-slugify = ">=3.0.2" -python-stdnum = "^1.15" +python-stdnum = "^1.16" python-swiftclient = "3.9.0" python-u2flib-server = "^5.0.1" python-u2flib_server = "^5.0.1" @@ -117,11 +124,10 @@ raven = "^6.10.0" redis = "2.10.5" reportlab = "3.3.0" requests = "2.20.0" -requests-mock = "^1.8.0" +requests-mock = "^1.9.3" requests-oauthlib = "1.1.0" requests-toolbelt = "0.9.1" retrying = "^1.3.3" -rotate_backups_s3 = "^0.3" serial = "^0.0.97" shapely = "1.6.4.post2" simplejson = "^3.17.2" @@ -129,27 +135,37 @@ slugify = "^0.0.1" sphinx = ">=1.6.7" sphinx-intl = "^2.0.1" sphinx-patchqueue = ">=1.0" -sphinx_rtd_theme = "^0.5.1" -sqlalchemy = "^1.3.22" +sphinx_rtd_theme = "^0.5.2" +sqlalchemy = "^1.4.19" statsd = "3.2.1" suds-jurko = "0.6" toml = "^0.10.2" twython = "^3.8.2" unidecode = "1.0.22" +unidiff = "^0.6.0" vatnumber = "1.2" vcrpy = ">=2.1.1" vcrpy-unittest = "^0.1.7" vobject = "0.9.3" voicent-python = "^1.0" webcolors = "1.10" -websocket-client = "^0.57.0" -wechatpy = "^1.8.14" +websocket-client = "^1.1.0" +wechatpy = "^1.8.15" +wget = "^3.2" wheel = "^0.36.2" xlrd = "1.0.0" xlwt = "1.3" +xmlformatter = "^0.2.2" xmltodict = "^0.12.0" zeep = "^4.0.0" zxcvbn = "^4.4.28" [tool.poetry.dev-dependencies] -websocket_client = "^0.57.0" +websocket_client = "^1.1.0" + +[tool.poetry.dependencies.black] +git = "https://github.com/psf/black.git" +rev = "21.6b0" + +[tool.poetry.dependencies.pylint-odoo] +git = "https://github.com/oca/pylint-odoo.git" diff --git a/requirements.txt b/requirements.txt index 62244c6..f847d19 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ # For script giturlparse agithub -gitpython +GitPython==3.1.12 PyYAML retrying xmltodict @@ -14,6 +14,7 @@ cython # For Odoo wheel phonenumbers +pytz==2017.3 # For OCA factur-x @@ -33,16 +34,14 @@ python-keystoneclient # For logical test docutils==0.16 flake8 -pylint-odoo -git+https://github.com/oca/pylint-odoo.git#egg=pylint-odoo +git+https://github.com/oca/pylint-odoo.git # oca-maintainers-tools # git+https://github.com/OCA/maintainer-tools.git#egg=oca-maintainers-tools xmlformatter html5print css-html-prettify BeautifulSoup4 -black -git+https://github.com/psf/black.git#egg=black +git+https://github.com/psf/black.git@21.6b0 # For updating poetry toml @@ -51,3 +50,7 @@ pandas==1.2.0 # For deployment cloudflare + +# For multilang_md.py +click +emoji diff --git a/script/poetry_update.py b/script/poetry_update.py index ed661f4..0db0774 100755 --- a/script/poetry_update.py +++ b/script/poetry_update.py @@ -46,7 +46,11 @@ def get_config(): def get_lst_requirements_txt(): - return list(Path(".").rglob("requirements.[tT][xX][tT]")) + # Ignore some item in list + lst = [a for a in Path(".").rglob("requirements.[tT][xX][tT]") + if not os.path.dirname(a).startswith('.repo/') and not os.path.dirname(a).startswith('.venv/') + ] + return lst def get_lst_manifest_py(): @@ -61,7 +65,8 @@ def combine_requirements(config): :param config: :return: """ - priority_filename_requirement = "odoo/requirements.txt" + priority_filename_requirement = "requirements.txt" + second_priority_filename_requirement = "odoo/requirements.txt" lst_sign = ("==", "!=", ">=", "<=", "<", ">", ";") lst_requirements = [] ignore_requirements = ["sys_platform == 'win32'", "python_version < '3.7'"] @@ -158,14 +163,19 @@ def combine_requirements(config): # Find the requirements file and print the conflict # Take the version from Odoo by default, else take the more recent odoo_value = None + erplibre_value = None for version_requirement in lst_version_requirement: filename_1 = dct_requirements_module_filename.get( version_requirement[0]) if priority_filename_requirement in filename_1: + erplibre_value = version_requirement[0] + elif second_priority_filename_requirement in filename_1: odoo_value = version_requirement[0] - break - if odoo_value: + if erplibre_value: + str_result_choose = f"Select {erplibre_value} because from ERPLibre" + result = erplibre_value + elif odoo_value: str_result_choose = f"Select {odoo_value} because from Odoo" result = odoo_value else: @@ -270,7 +280,12 @@ def get_manifest_external_dependencies(dct_requirements): def call_poetry_add_build_dependency(): - os.system("./script/poetry_add_build_dependency.sh") + """ + + :return: True if success + """ + status = os.system("./script/poetry_add_build_dependency.sh") + return status == 0 def get_list_ignored(): @@ -289,8 +304,9 @@ def main(): combine_requirements(config) if config.force and os.path.isfile("./poetry.lock"): os.remove("./poetry.lock") - call_poetry_add_build_dependency() - sorted_dependency_poetry(pyproject_toml_filename) + status = call_poetry_add_build_dependency() + if status: + sorted_dependency_poetry(pyproject_toml_filename) if __name__ == '__main__': From 705416d02112e897ef75cf6049c062f946a6de0e Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Sun, 27 Jun 2021 00:28:52 -0400 Subject: [PATCH 37/44] [FIX] remove duplicated dependency in debian installation --- script/install_debian_dependency.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/install_debian_dependency.sh b/script/install_debian_dependency.sh index 2dd617a..0a29e00 100755 --- a/script/install_debian_dependency.sh +++ b/script/install_debian_dependency.sh @@ -50,7 +50,7 @@ echo -e "\n--- Installing debian dependency --" sudo apt-get install git build-essential wget libxslt-dev libzip-dev libldap2-dev libsasl2-dev libpng12-0 gdebi-core libffi-dev libbz2-dev -y sudo apt-get install libmariadbd-dev -y # Dependencies for pyenv -sudo apt-get install make libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev liblzma-dev -y +sudo apt-get install make libssl-dev zlib1g-dev libreadline-dev libsqlite3-dev curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev liblzma-dev -y echo -e "\n---- Installing nodeJS NPM and rtlcss for LTR support ----" sudo apt-get install nodejs npm -y From bb4fc63fc20fb1fbc18dd7e4799f9336dc218883 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Sun, 27 Jun 2021 00:49:00 -0400 Subject: [PATCH 38/44] [ADD] makefile format script directory with format_script --- Makefile | 6 +- .../transform_python_to_code_writer.py | 707 ++++++++++++++---- .../transform_xml_to_code_writer.py | 74 +- script/db_restore.py | 64 +- script/deployment/get_public_ip.py | 2 +- script/deployment/update_dns_cloudflare.py | 91 ++- script/docker_update_version.py | 44 +- script/fork_github_repo/__init__.py | 160 ++-- script/fork_project.py | 65 +- script/fork_project_ERPLibre.py | 130 ++-- script/git_change_remote.py | 97 ++- script/git_change_remote_https_to_git.py | 45 +- script/git_diff_repo_manifest.py | 48 +- script/git_merge_repo_manifest.py | 46 +- script/git_repo_manifest.py | 71 +- script/git_repo_update_group.py | 19 +- script/git_show_code_diff_repo_manifest.py | 33 +- script/git_tool.py | 442 +++++++---- script/git_update_repo.py | 68 +- script/poetry_update.py | 163 ++-- script/pull_request_ERPLibre.py | 67 +- script/repo_remove_auto_install.py | 55 +- ...evert_git_diff_date_from_code_generator.py | 39 +- 23 files changed, 1754 insertions(+), 782 deletions(-) diff --git a/Makefile b/Makefile index d9f2062..9d91ea4 100644 --- a/Makefile +++ b/Makefile @@ -246,7 +246,7 @@ open_terminal: # format # ############ .PHONY: format -format: format_code_generator format_code_generator_template +format: format_code_generator format_code_generator_template format_script .PHONY: format_code_generator format_code_generator: @@ -258,6 +258,10 @@ format_code_generator_template: ./script/maintenance/black.sh ./addons/TechnoLibre_odoo-code-generator-template/ #./script/maintenance/prettier_xml.sh ./addons/TechnoLibre_odoo-code-generator-template/ +.PHONY: format_script +format_script: + ./script/maintenance/black.sh ./script/ + ########### # clean # ########### diff --git a/script/code_generator/transform_python_to_code_writer.py b/script/code_generator/transform_python_to_code_writer.py index 6030507..fae2585 100644 --- a/script/code_generator/transform_python_to_code_writer.py +++ b/script/code_generator/transform_python_to_code_writer.py @@ -5,6 +5,7 @@ import argparse import logging import subprocess from code_writer import CodeWriter + # import tokenize from script.git_tool import GitTool @@ -21,16 +22,22 @@ def get_config(): # TODO update description parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, - description='''\ + description="""\ Transform a python file in code writer format python file. -''', - epilog='''\ -''' +""", + epilog="""\ +""", + ) + parser.add_argument( + "-f", + "--file", + dest="file", + required=True, + help="Path of file to transform to code_writer.", + ) + parser.add_argument( + "-o", "--output", dest="output", help="The output file." ) - parser.add_argument('-f', '--file', dest="file", required=True, - help="Path of file to transform to code_writer.") - parser.add_argument('-o', '--output', dest="output", - help="The output file.") args = parser.parse_args() return args @@ -68,7 +75,11 @@ def main(): no_tab = 0 # Validate file format - out = subprocess.check_output(f"python -m tabnanny {config.file}", stderr=subprocess.STDOUT, shell=True) + out = subprocess.check_output( + f"python -m tabnanny {config.file}", + stderr=subprocess.STDOUT, + shell=True, + ) if out: print(out) sys.exit(1) @@ -82,14 +93,16 @@ def main(): cw.emit("cw = CodeWriter()") no_line = 1 - with open(config.file, 'r') as file: + with open(config.file, "r") as file: for line in file.readlines(): nb_tab, nb_space = count_space_tab(line) diff_tab = nb_tab - last_nb_tab new_line = line.strip() - new_line = new_line.replace("\"", "\\\"") + new_line = new_line.replace('"', '\\"') - status_no_tab = add_line(cw, new_line, no_line, nb_tab, no_tab, no_tab, nb_space) + status_no_tab = add_line( + cw, new_line, no_line, nb_tab, no_tab, no_tab, nb_space + ) if status_no_tab >= 0: no_tab = status_no_tab @@ -99,13 +112,15 @@ def main(): output = cw.render() if config.output: - with open(config.output, 'w') as file: + with open(config.output, "w") as file: file.write(output) else: print(output) -def add_line(cw, line, no_line, nb_indent, no_indent, init_no_intend, nb_space): +def add_line( + cw, line, no_line, nb_indent, no_indent, init_no_intend, nb_space +): """ Recursive check indent and write line :param cw: code_writer module @@ -123,25 +138,27 @@ def add_line(cw, line, no_line, nb_indent, no_indent, init_no_intend, nb_space): sys.exit(-1) if nb_indent == -1: - cw.emit("cw.emit(\"\")") + cw.emit('cw.emit("")') return 0 elif nb_indent == no_indent: if nb_indent == 0: - cw.emit(f"cw.emit(\"{line}\")") + cw.emit(f'cw.emit("{line}")') return 0 elif nb_indent == 1: if no_indent != init_no_intend: cw.emit(f"with cw.indent({4 + nb_space if nb_space else ''}):") with cw.indent(): - cw.emit(f"cw.emit(\"{line}\")") + cw.emit(f'cw.emit("{line}")') elif nb_indent == 2: if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") with cw.indent(): if no_indent != init_no_intend: - cw.emit(f"with cw.indent({4 + nb_space if nb_space else ''}):") + cw.emit( + f"with cw.indent({4 + nb_space if nb_space else ''}):" + ) with cw.indent(): - cw.emit(f"cw.emit(\"{line}\")") + cw.emit(f'cw.emit("{line}")') elif nb_indent == 3: if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") @@ -150,9 +167,12 @@ def add_line(cw, line, no_line, nb_indent, no_indent, init_no_intend, nb_space): cw.emit(f"with cw.indent():") with cw.indent(): if no_indent != init_no_intend: - cw.emit(f"with cw.indent({4 + nb_space if nb_space else ''}):") + cw.emit( + "with" + f" cw.indent({4 + nb_space if nb_space else ''}):" + ) with cw.indent(): - cw.emit(f"cw.emit(\"{line}\")") + cw.emit(f'cw.emit("{line}")') elif nb_indent == 4: if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") @@ -164,9 +184,12 @@ def add_line(cw, line, no_line, nb_indent, no_indent, init_no_intend, nb_space): cw.emit(f"with cw.indent():") with cw.indent(): if no_indent != init_no_intend: - cw.emit(f"with cw.indent({4 + nb_space if nb_space else ''}):") + cw.emit( + "with" + f" cw.indent({4 + nb_space if nb_space else ''}):" + ) with cw.indent(): - cw.emit(f"cw.emit(\"{line}\")") + cw.emit(f'cw.emit("{line}")') elif nb_indent == 5: if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") @@ -181,9 +204,12 @@ def add_line(cw, line, no_line, nb_indent, no_indent, init_no_intend, nb_space): cw.emit(f"with cw.indent():") with cw.indent(): if no_indent != init_no_intend: - cw.emit(f"with cw.indent({4 + nb_space if nb_space else ''}):") + cw.emit( + "with" + f" cw.indent({4 + nb_space if nb_space else ''}):" + ) with cw.indent(): - cw.emit(f"cw.emit(\"{line}\")") + cw.emit(f'cw.emit("{line}")') elif nb_indent == 6: if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") @@ -201,9 +227,12 @@ def add_line(cw, line, no_line, nb_indent, no_indent, init_no_intend, nb_space): cw.emit(f"with cw.indent():") with cw.indent(): if no_indent != init_no_intend: - cw.emit(f"with cw.indent({4 + nb_space if nb_space else ''}):") + cw.emit( + "with" + f" cw.indent({4 + nb_space if nb_space else ''}):" + ) with cw.indent(): - cw.emit(f"cw.emit(\"{line}\")") + cw.emit(f'cw.emit("{line}")') elif nb_indent == 7: if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") @@ -224,9 +253,12 @@ def add_line(cw, line, no_line, nb_indent, no_indent, init_no_intend, nb_space): cw.emit(f"with cw.indent():") with cw.indent(): if no_indent != init_no_intend: - cw.emit(f"with cw.indent({4 + nb_space if nb_space else ''}):") + cw.emit( + "with" + f" cw.indent({4 + nb_space if nb_space else ''}):" + ) with cw.indent(): - cw.emit(f"cw.emit(\"{line}\")") + cw.emit(f'cw.emit("{line}")') elif nb_indent == 8: if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") @@ -250,9 +282,12 @@ def add_line(cw, line, no_line, nb_indent, no_indent, init_no_intend, nb_space): cw.emit(f"with cw.indent():") with cw.indent(): if no_indent != init_no_intend: - cw.emit(f"with cw.indent({4 + nb_space if nb_space else ''}):") + cw.emit( + "with" + f" cw.indent({4 + nb_space if nb_space else ''}):" + ) with cw.indent(): - cw.emit(f"cw.emit(\"{line}\")") + cw.emit(f'cw.emit("{line}")') elif nb_indent == 9: if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") @@ -279,9 +314,12 @@ def add_line(cw, line, no_line, nb_indent, no_indent, init_no_intend, nb_space): cw.emit(f"with cw.indent():") with cw.indent(): if no_indent != init_no_intend: - cw.emit(f"with cw.indent({4 + nb_space if nb_space else ''}):") + cw.emit( + "with" + f" cw.indent({4 + nb_space if nb_space else ''}):" + ) with cw.indent(): - cw.emit(f"cw.emit(\"{line}\")") + cw.emit(f'cw.emit("{line}")') elif nb_indent == 10: if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") @@ -311,9 +349,14 @@ def add_line(cw, line, no_line, nb_indent, no_indent, init_no_intend, nb_space): cw.emit(f"with cw.indent():") with cw.indent(): if no_indent != init_no_intend: - cw.emit(f"with cw.indent({4 + nb_space if nb_space else ''}):") + cw.emit( + "with" + f" cw.indent({4 + nb_space if nb_space else ''}):" + ) with cw.indent(): - cw.emit(f"cw.emit(\"{line}\")") + cw.emit( + f'cw.emit("{line}")' + ) elif nb_indent == 11: if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") @@ -342,13 +385,26 @@ def add_line(cw, line, no_line, nb_indent, no_indent, init_no_intend, nb_space): if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with cw.indent():" + ) with cw.indent(): - if no_indent != init_no_intend: - cw.emit(f"with cw.indent({4 + nb_space if nb_space else ''}):") + if ( + no_indent + != init_no_intend + ): + cw.emit( + "with" + f" cw.indent({4 + nb_space if nb_space else ''}):" + ) with cw.indent(): - cw.emit(f"cw.emit(\"{line}\")") + cw.emit( + f'cw.emit("{line}")' + ) elif nb_indent == 12: if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") @@ -377,16 +433,35 @@ def add_line(cw, line, no_line, nb_indent, no_indent, init_no_intend, nb_space): if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if no_indent != init_no_intend: - cw.emit(f"with cw.indent({4 + nb_space if nb_space else ''}):") + if ( + no_indent + != init_no_intend + ): + cw.emit( + "with" + f" cw.indent({4 + nb_space if nb_space else ''}):" + ) with cw.indent(): - cw.emit(f"cw.emit(\"{line}\")") + cw.emit( + f'cw.emit("{line}")' + ) elif nb_indent == 13: if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") @@ -415,19 +490,44 @@ def add_line(cw, line, no_line, nb_indent, no_indent, init_no_intend, nb_space): if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if no_indent != init_no_intend: - cw.emit(f"with cw.indent({4 + nb_space if nb_space else ''}):") + if ( + no_indent + != init_no_intend + ): + cw.emit( + "with" + f" cw.indent({4 + nb_space if nb_space else ''}):" + ) with cw.indent(): - cw.emit(f"cw.emit(\"{line}\")") + cw.emit( + f'cw.emit("{line}")' + ) elif nb_indent == 14: if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") @@ -458,22 +558,53 @@ def add_line(cw, line, no_line, nb_indent, no_indent, init_no_intend, nb_space): if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if no_indent != init_no_intend: - cw.emit(f"with cw.indent({4 + nb_space if nb_space else ''}):") + if ( + no_indent + != init_no_intend + ): + cw.emit( + "with" + f" cw.indent({4 + nb_space if nb_space else ''}):" + ) with cw.indent(): - cw.emit(f"cw.emit(\"{line}\")") + cw.emit( + f'cw.emit("{line}")' + ) elif nb_indent == 15: if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") @@ -504,25 +635,63 @@ def add_line(cw, line, no_line, nb_indent, no_indent, init_no_intend, nb_space): if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent + - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if no_indent != init_no_intend: - cw.emit(f"with cw.indent({4 + nb_space if nb_space else ''}):") + if ( + no_indent + != init_no_intend + ): + cw.emit( + "with" + f" cw.indent({4 + nb_space if nb_space else ''}):" + ) with cw.indent(): - cw.emit(f"cw.emit(\"{line}\")") + cw.emit( + f'cw.emit("{line}")' + ) elif nb_indent == 16: if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") @@ -551,28 +720,72 @@ def add_line(cw, line, no_line, nb_indent, no_indent, init_no_intend, nb_space): if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent + - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent + - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if no_indent != init_no_intend: - cw.emit(f"with cw.indent({4 + nb_space if nb_space else ''}):") + if ( + no_indent + != init_no_intend + ): + cw.emit( + f"with cw.indent({4 + nb_space if nb_space else ''}):" + ) with cw.indent(): - cw.emit(f"cw.emit(\"{line}\")") + cw.emit( + f'cw.emit("{line}")' + ) elif nb_indent == 17: if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") @@ -601,31 +814,81 @@ def add_line(cw, line, no_line, nb_indent, no_indent, init_no_intend, nb_space): if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent + - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent + - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent + - 1 + > init_no_intend + ): + cw.emit( + f"with cw.indent():" + ) with cw.indent(): - if no_indent != init_no_intend: - cw.emit(f"with cw.indent({4 + nb_space if nb_space else ''}):") + if ( + no_indent + != init_no_intend + ): + cw.emit( + f"with cw.indent({4 + nb_space if nb_space else ''}):" + ) with cw.indent(): - cw.emit(f"cw.emit(\"{line}\")") + cw.emit( + f'cw.emit("{line}")' + ) elif nb_indent == 18: if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") @@ -656,34 +919,90 @@ def add_line(cw, line, no_line, nb_indent, no_indent, init_no_intend, nb_space): if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent + - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent + - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent + - 1 + > init_no_intend + ): + cw.emit( + f"with cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent + - 1 + > init_no_intend + ): + cw.emit( + f"with cw.indent():" + ) with cw.indent(): - if no_indent != init_no_intend: - cw.emit(f"with cw.indent({4 + nb_space if nb_space else ''}):") + if ( + no_indent + != init_no_intend + ): + cw.emit( + f"with cw.indent({4 + nb_space if nb_space else ''}):" + ) with cw.indent(): - cw.emit(f"cw.emit(\"{line}\")") + cw.emit( + f'cw.emit("{line}")' + ) elif nb_indent == 19: if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") @@ -716,48 +1035,126 @@ def add_line(cw, line, no_line, nb_indent, no_indent, init_no_intend, nb_space): if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent + - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent + - 1 + > init_no_intend + ): + cw.emit( + f"with" + f" cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent + - 1 + > init_no_intend + ): + cw.emit( + f"with cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent + - 1 + > init_no_intend + ): + cw.emit( + f"with cw.indent():" + ) with cw.indent(): - if nb_indent - 1 > init_no_intend: - cw.emit(f"with cw.indent():") + if ( + nb_indent + - 1 + > init_no_intend + ): + cw.emit( + f"with cw.indent():" + ) with cw.indent(): - if no_indent != init_no_intend: - cw.emit(f"with cw.indent({4 + nb_space if nb_space else ''}):") + if ( + no_indent + != init_no_intend + ): + cw.emit( + f"with cw.indent({4 + nb_space if nb_space else ''}):" + ) with cw.indent(): - cw.emit(f"cw.emit(\"{line}\")") + cw.emit( + f'cw.emit("{line}")' + ) return nb_indent else: if no_indent > nb_indent: # deindent - return add_line(cw, line, no_line, nb_indent, no_indent - 1, init_no_intend, nb_space) + return add_line( + cw, + line, + no_line, + nb_indent, + no_indent - 1, + init_no_intend, + nb_space, + ) else: # indent - return add_line(cw, line, no_line, nb_indent, no_indent + 1, init_no_intend, nb_space) + return add_line( + cw, + line, + no_line, + nb_indent, + no_indent + 1, + init_no_intend, + nb_space, + ) print("BUG") return -1 -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/script/code_generator/transform_xml_to_code_writer.py b/script/code_generator/transform_xml_to_code_writer.py index 46c8e3b..aa90052 100644 --- a/script/code_generator/transform_xml_to_code_writer.py +++ b/script/code_generator/transform_xml_to_code_writer.py @@ -20,16 +20,22 @@ def get_config(): # TODO update description parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, - description='''\ + description="""\ Transform a xml file in code writer format xml file. -''', - epilog='''\ -''' +""", + epilog="""\ +""", + ) + parser.add_argument( + "-f", + "--file", + dest="file", + required=True, + help="Path of file to transform to code_writer.", + ) + parser.add_argument( + "-o", "--output", dest="output", help="The output file." ) - parser.add_argument('-f', '--file', dest="file", required=True, - help="Path of file to transform to code_writer.") - parser.add_argument('-o', '--output', dest="output", - help="The output file.") args = parser.parse_args() return args @@ -55,7 +61,10 @@ def code_writer_deep_xml(nodes): if lst_comment: comment = f"# {lst_comment[0]}" - code_line = (f"E.{node.tagName}({str(dict(node.attributes.items()))})", value) + code_line = ( + f"E.{node.tagName}({str(dict(node.attributes.items()))})", + value, + ) lst_result.append((comment, code_line)) elif node.nodeType == Node.TEXT_NODE: if size_nodes == 1: @@ -102,31 +111,36 @@ def main(): print(f"Error, cannot parse {config.file}") sys.exit(1) - cw.emit('from lxml.builder import E') - cw.emit('from lxml import etree as ET') - cw.emit('from code_writer import CodeWriter') - cw.emit('') + cw.emit("from lxml.builder import E") + cw.emit("from lxml import etree as ET") + cw.emit("from code_writer import CodeWriter") + cw.emit("") cw.emit('print(\'\')') cw.emit('print("")') lst_function = [] comment_for_next_group = None - for odoo in mydoc.getElementsByTagName('odoo'): + for odoo in mydoc.getElementsByTagName("odoo"): for ir_view_item in odoo.childNodes: if ir_view_item.nodeType == Node.ELEMENT_NODE: # Show part of xml fct_name = "ma_fonction" lst_function.append(fct_name) - cw.emit(f'def {fct_name}():') + cw.emit(f"def {fct_name}():") with cw.indent(): cw.emit('"""') - for line in transform_string_to_list(ir_view_item.toprettyxml()): + for line in transform_string_to_list( + ir_view_item.toprettyxml() + ): cw.emit(line) cw.emit('"""') # Show comment if comment_for_next_group: - cw.emit(f'print(\'\')') + cw.emit( + "print('')" + ) comment_for_next_group = None attributes_root = dict(ir_view_item.attributes.items()) @@ -136,15 +150,21 @@ def main(): generate_code.generate_code(lst_out) child_root = generate_code.result - code = f'root = E.{ir_view_item.tagName}({str(attributes_root)}, {child_root})' + code = ( + "root =" + f" E.{ir_view_item.tagName}({str(attributes_root)}," + f" {child_root})" + ) for line in code.split("\n"): cw.emit(line) - cw.emit('content = ET.tostring(root, pretty_print=True)') + cw.emit("content = ET.tostring(root, pretty_print=True)") cw.emit() cw.emit("cw = CodeWriter()") - cw.emit('for line in content.decode("utf-8").split("\\n"):') + cw.emit( + 'for line in content.decode("utf-8").split("\\n"):' + ) with cw.indent(): cw.emit("with cw.indent():") with cw.indent(): @@ -161,13 +181,15 @@ def main(): output = cw.render() if config.output: - with open(config.output, 'w') as file: + with open(config.output, "w") as file: file.write(output) else: print(output) -def add_line(cw, line, no_line, nb_indent, no_indent, init_no_intend, nb_space): +def add_line( + cw, line, no_line, nb_indent, no_indent, init_no_intend, nb_space +): """ Recursive check indent and write line :param cw: code_writer module @@ -185,21 +207,21 @@ def add_line(cw, line, no_line, nb_indent, no_indent, init_no_intend, nb_space): sys.exit(-1) if nb_indent == -1: - cw.emit("cw.emit(\"\")") + cw.emit('cw.emit("")') return 0 elif nb_indent == no_indent: if nb_indent == 0: - cw.emit(f"cw.emit(\"{line}\")") + cw.emit(f'cw.emit("{line}")') return 0 elif nb_indent == 1: if no_indent != init_no_intend: cw.emit(f"with cw.indent({4 + nb_space if nb_space else ''}):") with cw.indent(): - cw.emit(f"cw.emit(\"{line}\")") + cw.emit(f'cw.emit("{line}")') elif nb_indent == 2: if nb_indent - 1 > init_no_intend: cw.emit(f"with cw.indent():") -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/script/db_restore.py b/script/db_restore.py index 67e69ce..bb49972 100755 --- a/script/db_restore.py +++ b/script/db_restore.py @@ -5,7 +5,7 @@ import argparse import logging from subprocess import check_output -new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '..')) +new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), "..")) sys.path.append(new_path) logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO")) @@ -22,20 +22,29 @@ def get_config(): # TODO update description parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, - description='''\ + description="""\ Restore database, use cache to clone to improve speed. -''', - epilog='''\ -''' +""", + epilog="""\ +""", ) # parser.add_argument('-d', '--dir', dest="dir", default="./", # help="Path of repo to change remote, including submodule.") - parser.add_argument('--database', help="Database to manipulate.") - parser.add_argument('--image', default="erplibre_base", - help="Image name to restore, from directory image_db, filename without '.zip'. " - "Example, use erplibre_base to use image erplibre_base.zip.") - parser.add_argument('--clean_cache', action="store_true", help="Delete all database cache to clone, " - "begin by _cache_.") + parser.add_argument("--database", help="Database to manipulate.") + parser.add_argument( + "--image", + default="erplibre_base", + help=( + "Image name to restore, from directory image_db, filename without" + " '.zip'. Example, use erplibre_base to use image" + " erplibre_base.zip." + ), + ) + parser.add_argument( + "--clean_cache", + action="store_true", + help="Delete all database cache to clone, begin by _cache_.", + ) args = parser.parse_args() return args @@ -52,7 +61,10 @@ def main(): if config.clean_cache: for db in lst_db_cache: _logger.info(f"## Delete {db} ##") - arg = f"./.venv/bin/python3 ./odoo/odoo-bin db --drop --database {db}" + arg = ( + "./.venv/bin/python3 ./odoo/odoo-bin db --drop --database" + f" {db}" + ) out = check_output(arg.split(" ")).decode() print(out) @@ -61,23 +73,35 @@ def main(): # Drop db if config.database in lst_db: _logger.info(f"## Drop {config.database} ##") - arg = f"./.venv/bin/python3 ./odoo/odoo-bin db --drop --database {config.database}" + arg = ( + "./.venv/bin/python3 ./odoo/odoo-bin db --drop --database" + f" {config.database}" + ) out = check_output(arg.split(" ")).decode() print(out) # Check cache exist if cache_database not in lst_db_cache: - _logger.info(f"## Create cache {cache_database} from image {config.image} ##") - arg = f"./.venv/bin/python3 ./odoo/odoo-bin db --restore --restore_image {config.image} " \ - f"--database {cache_database}" + _logger.info( + f"## Create cache {cache_database} from image" + f" {config.image} ##" + ) + arg = ( + "./.venv/bin/python3 ./odoo/odoo-bin db --restore" + f" --restore_image {config.image} --database {cache_database}" + ) out = check_output(arg.split(" ")).decode() print(out) # Clone database - _logger.info(f"## Clone cache {cache_database} to database {config.database} ##") - arg = f"./.venv/bin/python3 ./odoo/odoo-bin db --clone --from_database {cache_database} " \ - f"--database {config.database}" + _logger.info( + f"## Clone cache {cache_database} to database {config.database} ##" + ) + arg = ( + "./.venv/bin/python3 ./odoo/odoo-bin db --clone --from_database" + f" {cache_database} --database {config.database}" + ) out = check_output(arg.split(" ")).decode() print(out) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/script/deployment/get_public_ip.py b/script/deployment/get_public_ip.py index 4711da6..dcc3232 100755 --- a/script/deployment/get_public_ip.py +++ b/script/deployment/get_public_ip.py @@ -1,6 +1,6 @@ #!./.venv/bin/python import requests -r = requests.get(r'https://api.ipify.org') +r = requests.get(r"https://api.ipify.org") ip = r.text print(ip) diff --git a/script/deployment/update_dns_cloudflare.py b/script/deployment/update_dns_cloudflare.py index cd7a678..b87a7a4 100755 --- a/script/deployment/update_dns_cloudflare.py +++ b/script/deployment/update_dns_cloudflare.py @@ -19,26 +19,47 @@ def get_config(): # TODO update description parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, - description='''\ + description="""\ Can update all old_ip to new_ip. When auto_sync is enable: Check zone and name on cloudflare and compare with public ip, update all old ip with new ip if different. You need your profile in file ~/.cloudflare/cloudflare.cfg -''', - epilog='''\ -''' +""", + epilog="""\ +""", + ) + parser.add_argument( + "--profile", + required=True, + help="The profile of CloudFlare, check ~/.cloudflare/cloudflare.cfg.", + ) + parser.add_argument( + "--old_ip", required=False, help="Ip to search to update." + ) + parser.add_argument( + "--new_ip", required=False, help="Ip to replace the old ip." + ) + parser.add_argument( + "--dns_name", + required=False, + help="DNS name to output his ip and sync.", + ) + parser.add_argument( + "--zone_name", + required=False, + help="The CloudFlare zone name to check.", + ) + parser.add_argument("--delete", action="store_true") + parser.add_argument("--debug", action="store_true") + parser.add_argument("--raw", action="store_true") + parser.add_argument( + "--auto_sync", + action="store_true", + help=( + "Need this to use DNS name and zone name to sync public ip to" + " CloudFlare." + ), ) - parser.add_argument('--profile', required=True, - help="The profile of CloudFlare, check ~/.cloudflare/cloudflare.cfg.") - parser.add_argument('--old_ip', required=False, help="Ip to search to update.") - parser.add_argument('--new_ip', required=False, help="Ip to replace the old ip.") - parser.add_argument('--dns_name', required=False, help="DNS name to output his ip and sync.") - parser.add_argument('--zone_name', required=False, help="The CloudFlare zone name to check.") - parser.add_argument('--delete', action="store_true") - parser.add_argument('--debug', action="store_true") - parser.add_argument('--raw', action="store_true") - parser.add_argument('--auto_sync', action="store_true", - help="Need this to use DNS name and zone name to sync public ip to CloudFlare.") args = parser.parse_args() return args @@ -50,25 +71,28 @@ class ManageCloudFlare: @staticmethod def get_public_ip(): - r = requests.get(r'https://api.ipify.org') + r = requests.get(r"https://api.ipify.org") ip = r.text return ip def get_ip_cloudflare(self, zone_name, name): """Return ip from a zone and domain""" - zone = self.cf.zones.get(params={'name': zone_name}) + zone = self.cf.zones.get(params={"name": zone_name}) lst_zone = [a.get("id") for a in zone] for zone_id in lst_zone: lst_result_dns = self.cf.zones.dns_records.get(zone_id) for result_dns in lst_result_dns: - if result_dns.get("type") == "A" and result_dns.get("name") == name: + if ( + result_dns.get("type") == "A" + and result_dns.get("name") == name + ): return result_dns.get("content") def edit_cloudflare(self, old_ip, delete=False, new_ip=""): """Change ip of zone and name""" # TODO support smaller range - params = {'per_page': 500} + params = {"per_page": 500} zones = self.cf.zones.get(params=params) result = zones.get("result") if self.raw else zones lst_zone = [a.get("id") for a in result] @@ -80,12 +104,25 @@ class ManageCloudFlare: if dns.get("content") == old_ip: if delete: _logger.info(f"Delete {dns.get('name')}") - r = self.cf.zones.dns_records.delete(zone_id, dns.get("id")) + r = self.cf.zones.dns_records.delete( + zone_id, dns.get("id") + ) elif new_ip: - _logger.info(f"Update {dns.get('name')} with ip {new_ip}, old ip was {old_ip}") - dns_record = {'name': dns.get("name"), 'type': dns.get("type"), 'content': new_ip} - r = self.cf.zones.dns_records.post(zone_id, data=dns_record) - r = self.cf.zones.dns_records.delete(zone_id, dns.get("id")) + _logger.info( + f"Update {dns.get('name')} with ip {new_ip}, old" + f" ip was {old_ip}" + ) + dns_record = { + "name": dns.get("name"), + "type": dns.get("type"), + "content": new_ip, + } + r = self.cf.zones.dns_records.post( + zone_id, data=dns_record + ) + r = self.cf.zones.dns_records.delete( + zone_id, dns.get("id") + ) def main(): @@ -99,8 +136,10 @@ def main(): else: _logger.info(f"Nothing to do, same ip {actual_ip}") else: - cl.edit_cloudflare(config.old_ip, delete=config.delete, new_ip=config.new_ip) + cl.edit_cloudflare( + config.old_ip, delete=config.delete, new_ip=config.new_ip + ) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/script/docker_update_version.py b/script/docker_update_version.py index 8d5838a..56bb974 100755 --- a/script/docker_update_version.py +++ b/script/docker_update_version.py @@ -5,7 +5,7 @@ import argparse import logging import yaml -new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '..')) +new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), "..")) sys.path.append(new_path) from script.git_tool import GitTool @@ -24,17 +24,27 @@ def get_config(): # TODO update description parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, - description='''\ + description="""\ Update version of docker ready to commit. -''', - epilog='''\ -''' +""", + epilog="""\ +""", + ) + parser.add_argument( + "--version", required=True, help="Version of ERPLibre." + ) + parser.add_argument("--base", required=True, help="Docker base name.") + parser.add_argument("--prod", required=True, help="Docker prod name.") + parser.add_argument( + "--docker_compose_file", + default="./docker-compose.yml", + help="Docker compose file to update.", + ) + parser.add_argument( + "--docker_prod", + default="./docker/Dockerfile.prod.pkg", + help="Docker prod file to update.", ) - parser.add_argument('--version', required=True, help="Version of ERPLibre.") - parser.add_argument('--base', required=True, help="Docker base name.") - parser.add_argument('--prod', required=True, help="Docker prod name.") - parser.add_argument('--docker_compose_file', default="./docker-compose.yml", help="Docker compose file to update.") - parser.add_argument('--docker_prod', default="./docker/Dockerfile.prod.pkg", help="Docker prod file to update.") args = parser.parse_args() args.base_version = f"{args.base}:{args.version}" args.prod_version = f"{args.prod}:{args.version}" @@ -57,7 +67,7 @@ def get_config(): def edit_text(config): - with open(config.docker_compose_file, 'r') as f: + with open(config.docker_compose_file, "r") as f: lst_docker_info = f.readlines() if not lst_docker_info: @@ -70,18 +80,20 @@ def edit_text(config): if is_find: key = "image:" value = lst_docker_info[i] - lst_docker_info[i] = f"{value[:value.find(key) + len(key)]} {config.prod_version}\n" + lst_docker_info[ + i + ] = f"{value[:value.find(key) + len(key)]} {config.prod_version}\n" break if "ERPLibre" in docker_info: is_find = True i += 1 - with open(config.docker_compose_file, 'w') as f: + with open(config.docker_compose_file, "w") as f: f.writelines(lst_docker_info) def edit_docker_prod(config): - with open(config.docker_prod, 'r') as f: + with open(config.docker_prod, "r") as f: lst_docker_info = f.readlines() if not lst_docker_info: @@ -94,7 +106,7 @@ def edit_docker_prod(config): lst_docker_info[i] = f"FROM {config.base_version}\n" i += 1 - with open(config.docker_prod, 'w') as f: + with open(config.docker_prod, "w") as f: f.writelines(lst_docker_info) @@ -104,5 +116,5 @@ def main(): edit_docker_prod(config) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/script/fork_github_repo/__init__.py b/script/fork_github_repo/__init__.py index 1d7d081..5b209ca 100644 --- a/script/fork_github_repo/__init__.py +++ b/script/fork_github_repo/__init__.py @@ -8,7 +8,7 @@ from giturlparse import parse # pip install giturlparse from retrying import retry # pip install retrying import yaml # pip install PyYAML -DEFAULT_CONFIG_FILENAME = '~/.github/fork_github_repo.yaml' +DEFAULT_CONFIG_FILENAME = "~/.github/fork_github_repo.yaml" def github_url_argument(url): @@ -20,11 +20,11 @@ def github_url_argument(url): """ parsed_url = parse(url) if not parsed_url.valid: - raise argparse.ArgumentTypeError('%s is not a valid git URL' - % url) + raise argparse.ArgumentTypeError("%s is not a valid git URL" % url) if not parsed_url.github: - raise argparse.ArgumentTypeError('%s is not a GitHub repo' - % parsed_url.url) + raise argparse.ArgumentTypeError( + "%s is not a GitHub repo" % parsed_url.url + ) return url @@ -41,10 +41,10 @@ def get_config(): """ parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, - description='''\ + description="""\ Fork a GitHub repo, clone that repo to a local directory, add the upstream -remote, create an optional feature branch and checkout that branch''', - epilog='''\ +remote, create an optional feature branch and checkout that branch""", + epilog="""\ The config file with a default location of ~/.github/fork_github_repo.yaml contains the following settings: @@ -59,27 +59,40 @@ The file is YAML formatted and the contents look like this : github_token: 0123456789abcdef0123456789abcdef01234567 repo_dir: ~/Documents/github.com/example/ organization: -''' +""", ) parser.add_argument( - '-c', '--config', - help='Filename of the yaml config file (default : %s)' - % DEFAULT_CONFIG_FILENAME, + "-c", + "--config", + help="Filename of the yaml config file (default : %s)" + % DEFAULT_CONFIG_FILENAME, default=filename_argument(DEFAULT_CONFIG_FILENAME), - type=filename_argument) - parser.add_argument('url', help="GitHub URL of the upstream repo to fork", - type=github_url_argument) - parser.add_argument('branch', nargs='?', default=None, - help="Name of the feature branch to create") + type=filename_argument, + ) + parser.add_argument( + "url", + help="GitHub URL of the upstream repo to fork", + type=github_url_argument, + ) + parser.add_argument( + "branch", + nargs="?", + default=None, + help="Name of the feature branch to create", + ) args = parser.parse_args() if (args.config == filename_argument(DEFAULT_CONFIG_FILENAME)) and ( - not os.path.isfile(args.config)): - parser.error('Please create a config file at %s or point to one with ' - 'the --config option.' % DEFAULT_CONFIG_FILENAME) + not os.path.isfile(args.config) + ): + parser.error( + "Please create a config file at %s or point to one with " + "the --config option." % DEFAULT_CONFIG_FILENAME + ) if not os.path.isfile(args.config): raise argparse.ArgumentTypeError( - 'Could not find config file %s.' % args.config) - with open(args.config, 'r') as f: + "Could not find config file %s." % args.config + ) + with open(args.config, "r") as f: try: config = yaml.safe_load(f) if isinstance(config, dict): @@ -88,10 +101,12 @@ organization: else: raise argparse.ArgumentTypeError( 'Config contains %s of "%s" but it should be a dict' - % (type(config), config)) + % (type(config), config) + ) except yaml.YAMLError: raise argparse.ArgumentTypeError( - 'Could not parse YAML in %s' % args.config) + "Could not parse YAML in %s" % args.config + ) def get_list_fork_repo(upstream_url, github_token): @@ -105,9 +120,15 @@ def get_list_fork_repo(upstream_url, github_token): def fork_and_clone_repo( - upstream_url, github_token, repo_dir_root, branch_name=None, - upstream_name='upstream', organization_name=None, fork_only=False, - repo_root=None): + upstream_url, + github_token, + repo_dir_root, + branch_name=None, + upstream_name="upstream", + organization_name=None, + fork_only=False, + repo_root=None, +): """Fork a GitHub repo, clone that repo to a local directory, add the upstream remote, create an optional feature branch and checkout that branch @@ -130,26 +151,28 @@ def fork_and_clone_repo( # Fork the repo status, user = gh.user.get() - user_name = user['login'] if not organization_name else organization_name + user_name = user["login"] if not organization_name else organization_name status, forked_repo = gh.repos[user_name][parsed_url.repo].get() if status == 404: - status, upstream_repo = ( - gh.repos[parsed_url.owner][parsed_url.repo].get()) + status, upstream_repo = gh.repos[parsed_url.owner][ + parsed_url.repo + ].get() if status == 404: print("Unable to find repo %s" % upstream_url) exit(1) args = {} if organization_name: args["organization"] = organization_name - status, forked_repo = ( - gh.repos[parsed_url.owner][parsed_url.repo].forks.post(**args)) + status, forked_repo = gh.repos[parsed_url.owner][ + parsed_url.repo + ].forks.post(**args) if status == 404: print("Error when forking repo %s" % forked_repo) exit(1) else: - print("Forked %s to %s" % (upstream_url, forked_repo['html_url'])) + print("Forked %s to %s" % (upstream_url, forked_repo["html_url"])) elif status == 202: - print("Forked repo %s already exists" % forked_repo['full_name']) + print("Forked repo %s already exists" % forked_repo["full_name"]) elif status != 200: print("Status not supported: %s - %s" % (status, forked_repo)) exit(1) @@ -166,24 +189,30 @@ def fork_and_clone_repo( try: if branch_name: submodule_repo = retry( - wait_exponential_multiplier=1000, - stop_max_delay=15000 - )(repo_root.create_submodule)(repo_dir_root, repo_dir_root, - url=http_url, - branch=branch_name) + wait_exponential_multiplier=1000, stop_max_delay=15000 + )(repo_root.create_submodule)( + repo_dir_root, + repo_dir_root, + url=http_url, + branch=branch_name, + ) else: submodule_repo = retry( - wait_exponential_multiplier=1000, - stop_max_delay=15000 - )(repo_root.create_submodule)(repo_dir_root, repo_dir_root, - url=http_url) + wait_exponential_multiplier=1000, stop_max_delay=15000 + )(repo_root.create_submodule)( + repo_dir_root, repo_dir_root, url=http_url + ) except KeyError as e: if os.path.isdir(repo_dir_root): - print(f"Warning, submodule {repo_dir_root} already exist, " - f"you need to add it in stage.") + print( + f"Warning, submodule {repo_dir_root} already exist, " + "you need to add it in stage." + ) else: - print(f"\nERROR Cannot create submodule {repo_dir_root}." - f"Maybe you need to delete .git/modules/{repo_dir_root}\n") + print( + f"\nERROR Cannot create submodule {repo_dir_root}." + f"Maybe you need to delete .git/modules/{repo_dir_root}\n" + ) return # # Delete appropriate submodule and recreate_submodule # shutil.rmtree(f".git/modules/{repo_dir_root}", ignore_errors=True) @@ -219,14 +248,15 @@ def fork_and_clone_repo( # url=bare_repo.git_dir, branch='master') else: if os.path.isdir(repo_dir): - print("Directory %s already exists, assuming it's a clone" % repo_dir) + print( + "Directory %s already exists, assuming it's a clone" % repo_dir + ) cloned_repo = Repo(repo_dir) else: cloned_repo = retry( - wait_exponential_multiplier=1000, - stop_max_delay=15000 - )(Repo.clone_from)(forked_repo['ssh_url'], repo_dir) - print("Cloned %s to %s" % (forked_repo['ssh_url'], repo_dir)) + wait_exponential_multiplier=1000, stop_max_delay=15000 + )(Repo.clone_from)(forked_repo["ssh_url"], repo_dir) + print("Cloned %s to %s" % (forked_repo["ssh_url"], repo_dir)) # Create the remote upstream try: @@ -234,14 +264,14 @@ def fork_and_clone_repo( print('Remote "%s" already exists in %s' % (upstream_name, repo_dir)) except ValueError: upstream_remote = retry( - wait_exponential_multiplier=1000, - stop_max_delay=15000 + wait_exponential_multiplier=1000, stop_max_delay=15000 )(cloned_repo.create_remote)(upstream_name, upstream_url) print('Remote "%s" created for %s' % (upstream_name, upstream_url)) # Fetch the remote upstream retry(wait_exponential_multiplier=1000, stop_max_delay=15000)( - upstream_remote.fetch)() + upstream_remote.fetch + )() print('Remote "%s" fetched' % upstream_name) # Create and checkout the branch @@ -255,19 +285,25 @@ def fork_and_clone_repo( branch = cloned_repo.heads[branch_name] print('Branch "%s" already exists' % branch_name) if branch_name not in cloned_repo.remotes.origin.refs: - cloned_repo.remotes.origin.push(refspec='{}:{}'.format( - branch.path, branch.path)) + cloned_repo.remotes.origin.push( + refspec="{}:{}".format(branch.path, branch.path) + ) print('Branch "%s" pushed to origin' % branch_name) else: print('Branch "%s" already exists in remote origin' % branch_name) if branch.tracking_branch() is None: branch.set_tracking_branch( - cloned_repo.remotes.origin.refs[branch_name]) - print('Tracking branch "%s" setup for branch "%s"' % ( - cloned_repo.remotes.origin.refs[branch_name], branch_name)) + cloned_repo.remotes.origin.refs[branch_name] + ) + print( + 'Tracking branch "%s" setup for branch "%s"' + % (cloned_repo.remotes.origin.refs[branch_name], branch_name) + ) else: - print('Branch "%s" already setup to track "%s"' % ( - branch_name, cloned_repo.remotes.origin.refs[branch_name])) + print( + 'Branch "%s" already setup to track "%s"' + % (branch_name, cloned_repo.remotes.origin.refs[branch_name]) + ) branch.checkout() print('Branch "%s" checked out' % branch_name) return branch diff --git a/script/fork_project.py b/script/fork_project.py index 3837d58..3dc9541 100644 --- a/script/fork_project.py +++ b/script/fork_project.py @@ -6,7 +6,7 @@ import logging from git import Repo from retrying import retry # pip install retrying -new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '..')) +new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), "..")) sys.path.append(new_path) from script import fork_github_repo @@ -27,18 +27,30 @@ def get_config(): # TODO update description parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, - description='''\ -''', - epilog='''\ -''' + description="""\ +""", + epilog="""\ +""", + ) + parser.add_argument( + "-d", + "--dir", + dest="dir", + default="./", + help="Path of repo to change remote, including submodule.", + ) + parser.add_argument( + "--organization", + dest="organization", + default="ERPLibre", + help="Choose organization to fork and change all repo.", + ) + parser.add_argument( + "--github_token", + dest="github_token", + default=config.get(CST_EL_GITHUB_TOKEN), + help="GitHub token generated by user", ) - parser.add_argument('-d', '--dir', dest="dir", default="./", - help="Path of repo to change remote, including submodule.") - parser.add_argument('--organization', dest="organization", default="ERPLibre", - help="Choose organization to fork and change all repo.") - parser.add_argument('--github_token', dest="github_token", - default=config.get(CST_EL_GITHUB_TOKEN), - help="GitHub token generated by user") args = parser.parse_args() return args @@ -76,21 +88,28 @@ def main(): # for remote in working_repo.remotes: if remote_origin: repo_origin_info = GitTool.get_transformed_repo_info_from_url( - remote_origin.url, repo_path=repo.get("relative_path")) + remote_origin.url, repo_path=repo.get("relative_path") + ) if repo_origin_info.organization not in dct_remote_name.keys(): # Add remote upstream_remote = retry( - wait_exponential_multiplier=1000, - stop_max_delay=15000 - )(working_repo.create_remote)(repo_origin_info.organization, - repo_origin_info.url_https) - print('Remote "%s" created for %s' % ( - repo_origin_info.organization, repo_origin_info.url_https)) + wait_exponential_multiplier=1000, stop_max_delay=15000 + )(working_repo.create_remote)( + repo_origin_info.organization, repo_origin_info.url_https + ) + print( + 'Remote "%s" created for %s' + % ( + repo_origin_info.organization, + repo_origin_info.url_https, + ) + ) # Fetch the remote retry(wait_exponential_multiplier=1000, stop_max_delay=15000)( - upstream_remote.fetch)() + upstream_remote.fetch + )() print('Remote "%s" fetched' % repo_origin_info.organization) # working_repo.git.remote.remove("origin") upstream_name = organization_name @@ -99,7 +118,9 @@ def main(): # [, , ] _logger.info( - f"Fork {url} on dir {repo_dir_root} for organization {organization_name}") + f"Fork {url} on dir {repo_dir_root} for organization" + f" {organization_name}" + ) fork_github_repo.fork_and_clone_repo( url, @@ -117,5 +138,5 @@ def main(): GitTool().generate_install_locally() -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/script/fork_project_ERPLibre.py b/script/fork_project_ERPLibre.py index dbd198e..10f51e3 100644 --- a/script/fork_project_ERPLibre.py +++ b/script/fork_project_ERPLibre.py @@ -6,7 +6,7 @@ import logging from git import Repo import git -new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '..')) +new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), "..")) sys.path.append(new_path) from script.git_tool import GitTool @@ -26,24 +26,41 @@ def get_config(): # TODO update description parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, - description='''\ -''', - epilog='''\ -''' + description="""\ +""", + epilog="""\ +""", + ) + parser.add_argument( + "-d", + "--dir", + dest="dir", + default="./", + help="Path of repo to change remote, including submodule.", + ) + parser.add_argument( + "--organization", + dest="organization", + default="ERPLibre", + help="Choose organization to fork and change all repo.", + ) + parser.add_argument( + "--skip_fork", + action="store_true", + help="Ignore fork to generate only manifest.", + ) + parser.add_argument( + "-f", "--force", action="store_true", help="Force rewrite remote." + ) + parser.add_argument( + "--fast", action="store_true", help="Ignore if repo already exist." + ) + parser.add_argument( + "--github_token", + dest="github_token", + default=config.get(CST_EL_GITHUB_TOKEN), + help="GitHub token generated by user", ) - parser.add_argument('-d', '--dir', dest="dir", default="./", - help="Path of repo to change remote, including submodule.") - parser.add_argument('--organization', dest="organization", default="ERPLibre", - help="Choose organization to fork and change all repo.") - parser.add_argument("--skip_fork", action="store_true", - help="Ignore fork to generate only manifest.") - parser.add_argument('-f', "--force", action="store_true", - help="Force rewrite remote.") - parser.add_argument("--fast", action="store_true", - help="Ignore if repo already exist.") - parser.add_argument('--github_token', dest="github_token", - default=config.get(CST_EL_GITHUB_TOKEN), - help="GitHub token generated by user") args = parser.parse_args() return args @@ -58,12 +75,21 @@ def main(): raise ValueError("Missing github_token") organization_name = config.organization - lst_repo = git_tool.get_source_repo_addons(repo_path=config.dir, add_repo_root=True) - lst_repo_organization = [git_tool.get_transformed_repo_info_from_url( - a.get("url"), repo_path=config.dir, organization_force=organization_name, - is_submodule=a.get("is_submodule"), sub_path=a.get("sub_path"), - revision=a.get("revision"), clone_depth=a.get("clone_depth")) - for a in lst_repo] + lst_repo = git_tool.get_source_repo_addons( + repo_path=config.dir, add_repo_root=True + ) + lst_repo_organization = [ + git_tool.get_transformed_repo_info_from_url( + a.get("url"), + repo_path=config.dir, + organization_force=organization_name, + is_submodule=a.get("is_submodule"), + sub_path=a.get("sub_path"), + revision=a.get("revision"), + clone_depth=a.get("clone_depth"), + ) + for a in lst_repo + ] if not config.skip_fork: i = 0 @@ -71,7 +97,11 @@ def main(): for repo in lst_repo: i += 1 print(f"Nb element {i}/{total} - {repo.get('project_name')}") - if config.fast and repo.get("is_submodule") and os.path.isdir(repo.get("path")): + if ( + config.fast + and repo.get("is_submodule") + and os.path.isdir(repo.get("path")) + ): continue url = repo.get("url") @@ -83,16 +113,22 @@ def main(): # url, organization_force="ERPLibre", # is_submodule=repo.get("is_submodule"), # sub_path=repo.get("sub_path")) - git_tool.fork_repo(upstream_url=url, - github_token=github_token, - organization_name="ERPLibre") + git_tool.fork_repo( + upstream_url=url, + github_token=github_token, + organization_name="ERPLibre", + ) repo_info = git_tool.get_transformed_repo_info_from_url( - url, organization_force=organization_name, + url, + organization_force=organization_name, is_submodule=repo.get("is_submodule"), - sub_path=repo.get("sub_path")) - git_tool.fork_repo(upstream_url=url, - github_token=github_token, - organization_name=organization_name) + sub_path=repo.get("sub_path"), + ) + git_tool.fork_repo( + upstream_url=url, + github_token=github_token, + organization_name=organization_name, + ) # git_tool.add_and_fetch_remote(repo_info, root_repo=root_repo) continue @@ -104,18 +140,25 @@ def main(): if not remote_erplibre: repo_info = git_tool.get_transformed_repo_info_from_url( - url, organization_force="ERPLibre", + url, + organization_force="ERPLibre", is_submodule=repo.get("is_submodule"), - sub_path=repo.get("sub_path")) + sub_path=repo.get("sub_path"), + ) # git_tool.add_and_fetch_remote(repo_info) - git_tool.fork_repo(url, github_token, - organization_name=organization_name, - ) + git_tool.fork_repo( + url, + github_token, + organization_name=organization_name, + ) repo_info = git_tool.get_transformed_repo_info_from_url( - url, organization_force=organization_name, - is_submodule=repo.get("is_submodule"), sub_path=repo.get("sub_path")) + url, + organization_force=organization_name, + is_submodule=repo.get("is_submodule"), + sub_path=repo.get("sub_path"), + ) if remote_origin: working_repo.git.remote("remove", "origin") repo_info.organization = "origin" @@ -131,10 +174,11 @@ def main(): # Update origin to new repo # git_tool.generate_git_modules(lst_repo_organization, repo_path=config.dir) - git_tool.generate_repo_manifest(lst_repo_organization, - output=f"{config.dir}manifest/default.dev.xml") + git_tool.generate_repo_manifest( + lst_repo_organization, output=f"{config.dir}manifest/default.dev.xml" + ) git_tool.generate_install_locally() -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/script/git_change_remote.py b/script/git_change_remote.py index c66bb2e..972b37f 100755 --- a/script/git_change_remote.py +++ b/script/git_change_remote.py @@ -7,7 +7,7 @@ from git import Repo from retrying import retry # pip install retrying -new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '..')) +new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), "..")) sys.path.append(new_path) from script import git_tool @@ -27,28 +27,51 @@ def get_config(): # TODO update description parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, - description='''\ -''', - epilog='''\ -''' + description="""\ +""", + epilog="""\ +""", + ) + parser.add_argument( + "-d", + "--dir", + dest="dir", + default="./", + help="Path of repo to change remote, including submodule.", + ) + parser.add_argument( + "--github_token", + dest="github_token", + default=config.get(CST_EL_GITHUB_TOKEN), + help="GitHub token generated by user", + ) + parser.add_argument( + "--open_web_browser", + action="store_true", + help="Open web browser for each repo.", + ) + parser.add_argument( + "--generate_only_install_locally", + action="store_true", + help="Only generate script install_locally.sh.", + ) + parser.add_argument( + "--sync_to", + dest="sync_to", + help="Only synchronize matching repo, use path compare to repo.", + ) + parser.add_argument( + "--dry_sync", + dest="dry_sync", + action="store_true", + help="Don't apply modification when sync_to.", + ) + parser.add_argument( + "--sync_with_submodule", + dest="sync_with_submodule", + action="store_true", + help="Remote directory use submodule to sync.", ) - parser.add_argument('-d', '--dir', dest="dir", default="./", - help="Path of repo to change remote, including submodule.") - parser.add_argument('--github_token', dest="github_token", - default=config.get(CST_EL_GITHUB_TOKEN), - help="GitHub token generated by user") - parser.add_argument("--open_web_browser", action="store_true", - help="Open web browser for each repo.") - parser.add_argument("--generate_only_install_locally", action="store_true", - help="Only generate script install_locally.sh.") - parser.add_argument("--sync_to", dest="sync_to", - help="Only synchronize matching repo, use path compare to " - "repo.") - parser.add_argument("--dry_sync", dest="dry_sync", action="store_true", - help="Don't apply modification when sync_to.") - parser.add_argument("--sync_with_submodule", dest="sync_with_submodule", - action="store_true", - help="Remote directory use submodule to sync.") args = parser.parse_args() return args @@ -68,9 +91,11 @@ def main(): if config.sync_to[-1] != "/": config.sync_to += "/" gt = git_tool.GitTool() - result = gt.get_matching_repo(repo_compare_to=config.sync_to, - force_normalize_compare=True, - sync_with_submodule=config.sync_with_submodule) + result = gt.get_matching_repo( + repo_compare_to=config.sync_to, + force_normalize_compare=True, + sync_with_submodule=config.sync_with_submodule, + ) gt.sync_to(result, checkout_when_diff=not config.dry_sync) return @@ -109,28 +134,34 @@ def main(): # # print(f"ERROR, missing branch 12.0 for {repo_dir_root}") _logger.info( - f"Fork {url} on dir {repo_dir_root} for organization {organization_name}") + f"Fork {url} on dir {repo_dir_root} for organization" + f" {organization_name}" + ) try: upstream_remote = cloned_repo.remote(upstream_name) - print('Remote "%s" already exists in %s' % - (upstream_name, repo_dir_root)) + print( + 'Remote "%s" already exists in %s' + % (upstream_name, repo_dir_root) + ) except ValueError: upstream_remote = retry( - wait_exponential_multiplier=1000, - stop_max_delay=15000 + wait_exponential_multiplier=1000, stop_max_delay=15000 )(cloned_repo.create_remote)(upstream_name, upstream_url) print('Remote "%s" created for %s' % (upstream_name, upstream_url)) try: # Fetch the remote upstream retry(wait_exponential_multiplier=1000, stop_max_delay=15000)( - upstream_remote.fetch)() + upstream_remote.fetch + )() print('Remote "%s" fetched' % upstream_name) except Exception: - print(f"ERROR git {repo_dir_root} remote {upstream_name} not exist.") + print( + f"ERROR git {repo_dir_root} remote {upstream_name} not exist." + ) upstream_remote.remove(cloned_repo, upstream_name) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/script/git_change_remote_https_to_git.py b/script/git_change_remote_https_to_git.py index 05cd37c..c304167 100755 --- a/script/git_change_remote_https_to_git.py +++ b/script/git_change_remote_https_to_git.py @@ -9,7 +9,7 @@ import sys from git import Repo -new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '..')) +new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), "..")) sys.path.append(new_path) from script.git_tool import GitTool @@ -27,18 +27,32 @@ def get_config(): # TODO update description parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, - description='''\ -''', - epilog='''\ -''' + description="""\ +""", + epilog="""\ +""", + ) + parser.add_argument( + "-d", + "--dir", + dest="dir", + default="./", + help="Path of repo to change remote, including submodule.", + ) + parser.add_argument( + "-f", + "--upstream", + dest="upstream", + help=( + "Upstream name to change address https to git. " + "When empty, all upstream is updated." + ), + ) + parser.add_argument( + "--git_to_https", + action="store_true", + help="Replace all repo git to https.", ) - parser.add_argument('-d', '--dir', dest="dir", default="./", - help="Path of repo to change remote, including submodule.") - parser.add_argument('-f', '--upstream', dest="upstream", - help="Upstream name to change address https to git. " - "When empty, all upstream is updated.") - parser.add_argument("--git_to_https", action="store_true", - help="Replace all repo git to https.") args = parser.parse_args() return args @@ -61,8 +75,9 @@ def main(): continue repo_sm = Repo(repo_name) if upstream_name: - remote_upstream_name = [a for a in repo_sm.remotes - if upstream_name == a.name] + remote_upstream_name = [ + a for a in repo_sm.remotes if upstream_name == a.name + ] else: remote_upstream_name = [a for a in repo_sm.remotes] @@ -73,5 +88,5 @@ def main(): print(f'Remote "{remote.name}" update for {new_url}') -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/script/git_diff_repo_manifest.py b/script/git_diff_repo_manifest.py index 9e92e1d..35a5064 100755 --- a/script/git_diff_repo_manifest.py +++ b/script/git_diff_repo_manifest.py @@ -5,7 +5,7 @@ import argparse import logging from git import Repo -new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '..')) +new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), "..")) sys.path.append(new_path) from script.git_tool import GitTool @@ -24,13 +24,19 @@ def get_config(): formatter_class=argparse.RawDescriptionHelpFormatter, description="""Get git diff between manifest repo revision, diff revision input1 to input2 """, - epilog='''\ -''' + epilog="""\ +""", + ) + parser.add_argument( + "--input1", + required=True, + help="Compare input1 to input2. Input1 is older config.", + ) + parser.add_argument( + "--input2", + required=True, + help="Compare input1 to input2. Input2 is newer config.", ) - parser.add_argument('--input1', required=True, - help="Compare input1 to input2. Input1 is older config.") - parser.add_argument('--input2', required=True, - help="Compare input1 to input2. Input2 is newer config.") # parser.add_argument('--clear', action="store_true", # help="Create a new manifest and clear old configuration.") args = parser.parse_args() @@ -41,10 +47,16 @@ def main(): config = get_config() git_tool = GitTool() - dct_remote_1, dct_project_1, default_remote_1 = git_tool.get_manifest_xml_info( - filename=config.input1, add_root=True) - dct_remote_2, dct_project_2, default_remote_2 = git_tool.get_manifest_xml_info( - filename=config.input2, add_root=True) + ( + dct_remote_1, + dct_project_1, + default_remote_1, + ) = git_tool.get_manifest_xml_info(filename=config.input1, add_root=True) + ( + dct_remote_2, + dct_project_2, + default_remote_2, + ) = git_tool.get_manifest_xml_info(filename=config.input2, add_root=True) set_project_1 = set(dct_project_1.keys()) set_project_2 = set(dct_project_2.keys()) @@ -75,14 +87,18 @@ def main(): path1 = value1.get("@path") path2 = value2.get("@path") if path1 != path2: - print(f"WARNING id {i}, path of git are different. " - f"Input1 {path1}, input2 {path2}") + print( + f"WARNING id {i}, path of git are different. " + f"Input1 {path1}, input2 {path2}" + ) continue i += 1 result = "same" if old_revision == new_revision else "diff" - print(f"{i}/{total} - {result} - " - f"{path1} {key} old {old_revision} new {new_revision}") + print( + f"{i}/{total} - {result} - " + f"{path1} {key} old {old_revision} new {new_revision}" + ) default_arg = [f"{old_revision}..{new_revision}"] if old_revision != new_revision: # get git diff @@ -91,5 +107,5 @@ def main(): print(status) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/script/git_merge_repo_manifest.py b/script/git_merge_repo_manifest.py index 7530044..865c366 100755 --- a/script/git_merge_repo_manifest.py +++ b/script/git_merge_repo_manifest.py @@ -5,7 +5,7 @@ import argparse import logging import copy -new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '..')) +new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), "..")) sys.path.append(new_path) from script.git_tool import GitTool @@ -23,15 +23,18 @@ def get_config(): parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description="""Replace revision field in input2 from input1 if existing, create an output of new manifest.""", - epilog='''\ -''' + epilog="""\ +""", + ) + parser.add_argument( + "--input1", required=True, help="First manifest to merge into input2." + ) + parser.add_argument( + "--input2", required=True, help="Second manifest, overwrite by input1." + ) + parser.add_argument( + "--output", required=True, help="Output of new manifest" ) - parser.add_argument('--input1', required=True, - help="First manifest to merge into input2.") - parser.add_argument('--input2', required=True, - help="Second manifest, overwrite by input1.") - parser.add_argument('--output', required=True, - help="Output of new manifest") # parser.add_argument('--clear', action="store_true", # help="Create a new manifest and clear old configuration.") args = parser.parse_args() @@ -42,10 +45,16 @@ def main(): config = get_config() git_tool = GitTool() - dct_remote_1, dct_project_1, default_remote_1 = git_tool.get_manifest_xml_info( - filename=config.input1, add_root=True) - dct_remote_2, dct_project_2, default_remote_2 = git_tool.get_manifest_xml_info( - filename=config.input2, add_root=True) + ( + dct_remote_1, + dct_project_1, + default_remote_1, + ) = git_tool.get_manifest_xml_info(filename=config.input1, add_root=True) + ( + dct_remote_2, + dct_project_2, + default_remote_2, + ) = git_tool.get_manifest_xml_info(filename=config.input2, add_root=True) dct_remote_3 = copy.deepcopy(dct_remote_2) dct_project_3 = copy.deepcopy(dct_project_2) @@ -59,10 +68,13 @@ def main(): dct_project_3[key]["@dest-branch"] = "12.0" # Update origin to new repo - git_tool.generate_repo_manifest(dct_remote=dct_remote_3, dct_project=dct_project_3, - output=config.output, - default_remote=default_remote_2) + git_tool.generate_repo_manifest( + dct_remote=dct_remote_3, + dct_project=dct_project_3, + output=config.output, + default_remote=default_remote_2, + ) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/script/git_repo_manifest.py b/script/git_repo_manifest.py index cf6b390..913d006 100755 --- a/script/git_repo_manifest.py +++ b/script/git_repo_manifest.py @@ -4,7 +4,7 @@ import sys import argparse import logging -new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '..')) +new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), "..")) sys.path.append(new_path) from script.git_tool import GitTool @@ -21,17 +21,29 @@ def get_config(): # TODO update description parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, - description='''\ -''', - epilog='''\ -''' + description="""\ +""", + epilog="""\ +""", + ) + parser.add_argument( + "-d", + "--dir", + dest="dir", + default="./", + help="Path of repo to change remote, including submodule.", + ) + parser.add_argument( + "--clear", + action="store_true", + help="Create a new manifest and clear old configuration.", + ) + parser.add_argument( + "-m", + "--manifest", + default="manifest/default.dev.xml", + help="The manifest file path to generate.", ) - parser.add_argument('-d', '--dir', dest="dir", default="./", - help="Path of repo to change remote, including submodule.") - parser.add_argument('--clear', action="store_true", - help="Create a new manifest and clear old configuration.") - parser.add_argument('-m', '--manifest', default="manifest/default.dev.xml", - help="The manifest file path to generate.") args = parser.parse_args() return args @@ -40,26 +52,39 @@ def main(): config = get_config() git_tool = GitTool() - lst_repo = git_tool.get_source_repo_addons(repo_path=config.dir, add_repo_root=True) - lst_repo_organization = [git_tool.get_transformed_repo_info_from_url( - a.get("url"), repo_path=config.dir, get_obj=True, - is_submodule=a.get("is_submodule"), sub_path=a.get("sub_path"), - revision=a.get("revision"), clone_depth=a.get("clone_depth")) - for a in lst_repo] + lst_repo = git_tool.get_source_repo_addons( + repo_path=config.dir, add_repo_root=True + ) + lst_repo_organization = [ + git_tool.get_transformed_repo_info_from_url( + a.get("url"), + repo_path=config.dir, + get_obj=True, + is_submodule=a.get("is_submodule"), + sub_path=a.get("sub_path"), + revision=a.get("revision"), + clone_depth=a.get("clone_depth"), + ) + for a in lst_repo + ] # Update origin to new repo if not config.clear: dct_remote, dct_project, _ = git_tool.get_manifest_xml_info( - repo_path=config.dir, add_root=True) + repo_path=config.dir, add_root=True + ) else: dct_remote = {} dct_project = {} - git_tool.generate_repo_manifest(lst_repo_organization, - output=f"{config.dir}{config.manifest}", - dct_remote=dct_remote, dct_project=dct_project, - keep_original=True) + git_tool.generate_repo_manifest( + lst_repo_organization, + output=f"{config.dir}{config.manifest}", + dct_remote=dct_remote, + dct_project=dct_project, + keep_original=True, + ) git_tool.generate_install_locally() -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/script/git_repo_update_group.py b/script/git_repo_update_group.py index 5c160f5..63614f2 100755 --- a/script/git_repo_update_group.py +++ b/script/git_repo_update_group.py @@ -6,7 +6,7 @@ import logging from git import Repo import git -new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '..')) +new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), "..")) sys.path.append(new_path) from script.git_tool import GitTool @@ -25,14 +25,17 @@ def get_config(): # TODO update description parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, - description='''\ + description="""\ Update config.conf file with group specified in manifest file. -''', - epilog='''\ -''' +""", + epilog="""\ +""", + ) + parser.add_argument( + "--group", + default="", + help="Prod by default, use 'dev' for manifest/default.dev.xml", ) - parser.add_argument('--group', default="", - help="Prod by default, use 'dev' for manifest/default.dev.xml") args = parser.parse_args() return args @@ -46,5 +49,5 @@ def main(): git_tool.generate_install_locally(filter_group=filter_group) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/script/git_show_code_diff_repo_manifest.py b/script/git_show_code_diff_repo_manifest.py index d8e4741..429c186 100755 --- a/script/git_show_code_diff_repo_manifest.py +++ b/script/git_show_code_diff_repo_manifest.py @@ -6,7 +6,7 @@ import logging from git import Repo from git.exc import GitCommandError -new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '..')) +new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), "..")) sys.path.append(new_path) from script.git_tool import GitTool @@ -24,11 +24,15 @@ def get_config(): parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description="""Compare actual code with a manifest.""", - epilog='''\ -''' + epilog="""\ +""", + ) + parser.add_argument( + "-m", + "--manifest", + required=True, + help="The manifest to compare with actual code.", ) - parser.add_argument('-m', '--manifest', required=True, - help="The manifest to compare with actual code.") args = parser.parse_args() return args @@ -37,8 +41,12 @@ def main(): config = get_config() git_tool = GitTool() - dct_remote, dct_project, default_remote = git_tool.get_manifest_xml_info(filename=config.manifest, add_root=True) - default_branch_name = default_remote.get("@revision", git_tool.default_branch) + dct_remote, dct_project, default_remote = git_tool.get_manifest_xml_info( + filename=config.manifest, add_root=True + ) + default_branch_name = default_remote.get( + "@revision", git_tool.default_branch + ) i = 0 total = len(dct_project) for name, project in dct_project.items(): @@ -57,7 +65,9 @@ def main(): # TODO maybe need to check divergence with local branch and not remote branch commit_head = git_repo.git.rev_parse("HEAD") try: - commit_branch = git_repo.git.rev_parse(f"{organization}/{branch_name}") + commit_branch = git_repo.git.rev_parse( + f"{organization}/{branch_name}" + ) except GitCommandError: print("ERROR Something wrong with this repo.") continue @@ -66,10 +76,13 @@ def main(): else: print("PASS Not on specified branch, no divergence.") elif branch_name != value: - print(f"ERROR, manifest revision is {branch_name} and actual revision is {value}.") + print( + f"ERROR, manifest revision is {branch_name} and actual" + f" revision is {value}." + ) else: print("PASS") -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/script/git_tool.py b/script/git_tool.py index f91cb8b..296e25d 100644 --- a/script/git_tool.py +++ b/script/git_tool.py @@ -59,13 +59,17 @@ class GitTool: return url, url_https, url_git - def get_transformed_repo_info_from_url(self, url: str, repo_path: str = "./", - get_obj: bool = True, - is_submodule: bool = True, - organization_force: str = None, - sub_path: str = "addons", - revision: str = "", - clone_depth: str = "") -> object: + def get_transformed_repo_info_from_url( + self, + url: str, + repo_path: str = "./", + get_obj: bool = True, + is_submodule: bool = True, + organization_force: str = None, + sub_path: str = "addons", + revision: str = "", + clone_depth: str = "", + ) -> object: """ :param url: @@ -99,8 +103,8 @@ class GitTool: relative_path = os.path.normpath(relative_path) original_organization = organization - url_https_original_organization = url_https[:url_https.rfind("/")] - project_name = url_https[url_https.rfind("/") + 1:] + url_https_original_organization = url_https[: url_https.rfind("/")] + project_name = url_https[url_https.rfind("/") + 1 :] # begin_original = url_git[url_git.find(":") + 1:] # original_organization = begin_original[:begin_original.find("/")] if organization_force: @@ -109,7 +113,7 @@ class GitTool: url_split[3] = organization url_https = "/".join(url_split) url, _, url_git = self.get_url(url_https) - url_https_organization = url_https[:url_https.rfind("/")] + url_https_organization = url_https[: url_https.rfind("/")] d = { "url": url, @@ -132,15 +136,26 @@ class GitTool: return Struct(**d) return d - def get_repo_info(self, repo_path: str = "./", - add_root: bool = False, is_manifest: bool = True, filter_group=None): + def get_repo_info( + self, + repo_path: str = "./", + add_root: bool = False, + is_manifest: bool = True, + filter_group=None, + ): if is_manifest: - return self.get_repo_info_manifest_xml(repo_path=repo_path, - add_root=add_root, filter_group=filter_group) - return self.get_repo_info_submodule(repo_path=repo_path, add_root=add_root) + return self.get_repo_info_manifest_xml( + repo_path=repo_path, + add_root=add_root, + filter_group=filter_group, + ) + return self.get_repo_info_submodule( + repo_path=repo_path, add_root=add_root + ) - def get_repo_info_submodule(self, repo_path: str = "./", - add_root: bool = False) -> list: + def get_repo_info_submodule( + self, repo_path: str = "./", add_root: bool = False + ) -> list: """ Get information about submodule from repo_path :param repo_path: path of repo to get information about submodule @@ -166,7 +181,7 @@ class GitTool: first_execution = True for line in txt: no_line += 1 - if line[:12] == "[submodule \"": + if line[:12] == '[submodule "': if not first_execution: data = { "url": url, @@ -220,8 +235,9 @@ class GitTool: lst_repo = sorted(lst_repo, key=lambda k: k.get("name")) return lst_repo - def get_repo_info_manifest_xml(self, repo_path: str = "./", - add_root: bool = False, filter_group=None) -> list: + def get_repo_info_manifest_xml( + self, repo_path: str = "./", add_root: bool = False, filter_group=None + ) -> list: """ Get information about manifest of Repo from repo_path :param repo_path: path of repo to get information about submodule @@ -255,7 +271,7 @@ class GitTool: dct_remote = {a.get("@name"): a.get("@fetch") for a in lst_remote} for project in lst_project: groups = project.get("@groups") - lst_group = groups.split(',') if groups else [] + lst_group = groups.split(",") if groups else [] # Continue if lst_filter exist and group in filter for group in lst_group: if lst_filter_group and group not in lst_filter_group: @@ -290,9 +306,11 @@ class GitTool: try: url = repo_root.git.remote("get-url", "origin") except Exception as e: - print(f"WARNING: Missing origin remote, use default url " - f"{DEFAULT_REMOTE_URL}. Suggest to add a remote origin: \n" - f"> git remote add origin {DEFAULT_REMOTE_URL}") + print( + "WARNING: Missing origin remote, use default url " + f"{DEFAULT_REMOTE_URL}. Suggest to add a remote origin: \n" + f"> git remote add origin {DEFAULT_REMOTE_URL}" + ) url = DEFAULT_REMOTE_URL url, url_https, url_git = self.get_url(url) @@ -308,8 +326,9 @@ class GitTool: lst_repo = sorted(lst_repo, key=lambda k: k.get("name")) return lst_repo - def get_manifest_xml_info(self, repo_path: str = "./", filename=None, - add_root: bool = False) -> list: + def get_manifest_xml_info( + self, repo_path: str = "./", filename=None, add_root: bool = False + ) -> list: """ Get contain of manifest :param repo_path: path of repo to get information about submodule @@ -366,15 +385,22 @@ class GitTool: def generate_install_locally(self, repo_path="./", filter_group=None): filename_locally = f"{repo_path}script/install_locally.sh" - lst_repo = self.get_repo_info(repo_path=repo_path, filter_group=filter_group) + lst_repo = self.get_repo_info( + repo_path=repo_path, filter_group=filter_group + ) lst_result = [] for repo in lst_repo: # Exception, ignore addons/OCA_web and root - if "addons/OCA_web" == repo.get("path") or "odoo" == repo.get("path") or \ - "ERPLibre_image_db" == repo.get("path"): + if ( + "addons/OCA_web" == repo.get("path") + or "odoo" == repo.get("path") + or "ERPLibre_image_db" == repo.get("path") + ): continue - str_repo = f' printf "${{EL_HOME}}/{repo.get("path")}," >> ' \ - f'${{EL_CONFIG_FILE}}\n' + str_repo = ( + f' printf "${{EL_HOME}}/{repo.get("path")}," >> ' + "${EL_CONFIG_FILE}\n" + ) lst_result.append(str_repo) with open(filename_locally) as file: all_lines = file.readlines() @@ -383,8 +409,10 @@ class GitTool: find_index = False index_find = 0 for line in all_lines: - if not find_index and \ - "if [[ ${EL_MINIMAL_ADDONS} = \"False\" ]]; then\n" == line: + if ( + not find_index + and 'if [[ ${EL_MINIMAL_ADDONS} = "False" ]]; then\n' == line + ): index_find = index + 1 for insert_line in lst_result: all_lines.insert(index_find, insert_line) @@ -398,8 +426,10 @@ class GitTool: index += 1 if not find_index: - print(f"ERROR cannot regenerate file {filename_locally}, " - f"did you change the header?") + print( + f"ERROR cannot regenerate file {filename_locally}, " + "did you change the header?" + ) # create file with open(filename_locally, mode="w") as file: @@ -409,9 +439,15 @@ class GitTool: def str_insert(source_str, insert_str, pos): return source_str[:pos] + insert_str + source_str[pos:] - def generate_repo_manifest(self, lst_repo: List[Struct] = [], output: str = "", - dct_remote={}, dct_project={}, default_remote=None, - keep_original=False): + def generate_repo_manifest( + self, + lst_repo: List[Struct] = [], + output: str = "", + dct_remote={}, + dct_project={}, + default_remote=None, + keep_original=False, + ): """ Generate repo manifest :param lst_repo: optional, update manifest with list_repo @@ -424,7 +460,9 @@ class GitTool: :return: """ if not output: - raise Exception("Cannot generate manifest with missing output filename.") + raise Exception( + "Cannot generate manifest with missing output filename." + ) lst_remote = [] lst_remote_name = [] lst_project = [] @@ -433,28 +471,40 @@ class GitTool: # Fill with configuration for dct_value in dct_remote.values(): - lst_remote.append(OrderedDict( - [('@name', dct_value.get("@name")), - ('@fetch', dct_value.get("@fetch"))] - )) + lst_remote.append( + OrderedDict( + [ + ("@name", dct_value.get("@name")), + ("@fetch", dct_value.get("@fetch")), + ] + ) + ) lst_remote_name.append(dct_value.get("@name")) for dct_value in dct_project.values(): lst_project_info = [ - ('@name', dct_value.get("@name")), - ('@path', dct_value.get("@path")), + ("@name", dct_value.get("@name")), + ("@path", dct_value.get("@path")), ] if "@remote" in dct_value.keys(): - lst_project_info.append(('@remote', dct_value.get("@remote"))) + lst_project_info.append(("@remote", dct_value.get("@remote"))) if "@revision" in dct_value.keys(): - lst_project_info.append(('@revision', dct_value.get("@revision"))) + lst_project_info.append( + ("@revision", dct_value.get("@revision")) + ) if "@clone-depth" in dct_value.keys(): - lst_project_info.append(('@clone-depth', dct_value.get("@clone-depth"))) + lst_project_info.append( + ("@clone-depth", dct_value.get("@clone-depth")) + ) if "@groups" in dct_value.keys(): - lst_project_info.append(('@groups', dct_value.get("@groups"))) + lst_project_info.append(("@groups", dct_value.get("@groups"))) if "@upstream" in dct_value.keys(): - lst_project_info.append(('@upstream', dct_value.get("@upstream"))) + lst_project_info.append( + ("@upstream", dct_value.get("@upstream")) + ) if "@dest-branch" in dct_value.keys(): - lst_project_info.append(('@dest-branch', dct_value.get("@dest-branch"))) + lst_project_info.append( + ("@dest-branch", dct_value.get("@dest-branch")) + ) lst_project.append(OrderedDict(lst_project_info)) lst_project_name.append(dct_value.get("@name")) @@ -463,64 +513,97 @@ class GitTool: if not repo.is_submodule: # Default if lst_default: - raise Exception("Cannot have many root repo. " - "Validate why 2 or more is not submodule.") - lst_default.append(OrderedDict([ - ('@remote', repo.original_organization), - ('@revision', DEFAULT_BRANCH), - ('@sync-j', "4"), - ('@sync-c', "true"), - ])) + raise Exception( + "Cannot have many root repo. " + "Validate why 2 or more is not submodule." + ) + lst_default.append( + OrderedDict( + [ + ("@remote", repo.original_organization), + ("@revision", DEFAULT_BRANCH), + ("@sync-j", "4"), + ("@sync-c", "true"), + ] + ) + ) else: - if keep_original and repo.project_name not in dct_project.keys(): + if ( + keep_original + and repo.project_name not in dct_project.keys() + ): # Exception, create a new remote to keep tracking on original - original_organization = f"{repo.original_organization}_origin" + original_organization = ( + f"{repo.original_organization}_origin" + ) else: original_organization = repo.original_organization # Add remote, only unique remote if original_organization not in lst_remote_name: - lst_remote.append(OrderedDict( - [('@name', original_organization), - ('@fetch', repo.url_https_organization + "/")] - )) + lst_remote.append( + OrderedDict( + [ + ("@name", original_organization), + ("@fetch", repo.url_https_organization + "/"), + ] + ) + ) lst_remote_name.append(repo.original_organization) # Add project, only unique project if repo.project_name not in lst_project_name: lst_project_name.append(repo.project_name) lst_project_info = [ - ('@name', repo.project_name), - ('@path', repo.path), - ('@remote', original_organization), + ("@name", repo.project_name), + ("@path", repo.path), + ("@remote", original_organization), ] if repo.revision: - lst_project_info.append(('@revision', repo.revision)) + lst_project_info.append(("@revision", repo.revision)) if repo.clone_depth: - lst_project_info.append(('@clone-depth', repo.clone_depth)) + lst_project_info.append( + ("@clone-depth", repo.clone_depth) + ) if repo.sub_path == "addons": - lst_project_info.append(('@groups', "addons")) + lst_project_info.append(("@groups", "addons")) else: - lst_project_info.append(('@groups', "odoo")) + lst_project_info.append(("@groups", "odoo")) lst_project.append(OrderedDict(lst_project_info)) if default_remote and not lst_default: - lst_default.append(OrderedDict([ - ('@remote', default_remote.get("@remote")), - ('@revision', DEFAULT_BRANCH), - ('@sync-j', "4"), - ('@sync-c', "true"), - ])) + lst_default.append( + OrderedDict( + [ + ("@remote", default_remote.get("@remote")), + ("@revision", DEFAULT_BRANCH), + ("@sync-j", "4"), + ("@sync-c", "true"), + ] + ) + ) # Order in alphabetic lst_order_remote = sorted(lst_remote, key=lambda key: key.get("@name")) - lst_order_default = sorted(lst_default, key=lambda key: key.get("@remote")) - lst_order_project = sorted(lst_project, key=lambda key: key.get("@name")) + lst_order_default = sorted( + lst_default, key=lambda key: key.get("@remote") + ) + lst_order_project = sorted( + lst_project, key=lambda key: key.get("@name") + ) dct_repo = OrderedDict( - [('manifest', OrderedDict([ - ('remote', lst_order_remote), - ('default', lst_order_default), - ('project', lst_order_project), - ]))]) + [ + ( + "manifest", + OrderedDict( + [ + ("remote", lst_order_remote), + ("default", lst_order_default), + ("project", lst_order_project), + ] + ), + ) + ] + ) str_xml_text = xmltodict.unparse(dct_repo, pretty=True) pos_insert = str_xml_text.rfind("") @@ -541,20 +624,26 @@ class GitTool: str_xml_text = str_xml_text.replace("> 5 and url[0:4] == "http" and url[-4:] != ".git": url = f"{url}.git" - repo_info = self.get_transformed_repo_info_from_url(url, - repo_path=repo_path, - get_obj=False, - sub_path=path, - revision=revision, - clone_depth=clone_depth) + repo_info = self.get_transformed_repo_info_from_url( + url, + repo_path=repo_path, + get_obj=False, + sub_path=path, + revision=revision, + clone_depth=clone_depth, + ) lst_result.append(repo_info) return lst_result @@ -634,11 +726,18 @@ class GitTool: with open(file) as xml: xml_as_string = xml.read() xml_dict = xmltodict.parse(xml_as_string, dict_constructor=dict) - manifest_filename = xml_dict.get("manifest").get("include").get("@name") + manifest_filename = ( + xml_dict.get("manifest").get("include").get("@name") + ) return manifest_filename - def get_matching_repo(self, actual_repo="./", repo_compare_to="./", - force_normalize_compare=False, sync_with_submodule=False): + def get_matching_repo( + self, + actual_repo="./", + repo_compare_to="./", + force_normalize_compare=False, + sync_with_submodule=False, + ): """ Compare repo with .gitmodules files :param actual_repo: @@ -653,12 +752,15 @@ class GitTool: # set_actual_repo = set( # [a[a.find("_") + 1:] for a in dct_repo_info_actual.keys()]) - dct_repo_info_actual_adapted = {key[key.find("_") + 1:]: item for key, item in - dct_repo_info_actual.items()} + dct_repo_info_actual_adapted = { + key[key.find("_") + 1 :]: item + for key, item in dct_repo_info_actual.items() + } set_actual_repo = set(dct_repo_info_actual_adapted.keys()) - lst_repo_info_compare = self.get_repo_info(repo_compare_to, - is_manifest=not sync_with_submodule) + lst_repo_info_compare = self.get_repo_info( + repo_compare_to, is_manifest=not sync_with_submodule + ) if force_normalize_compare: for repo_info in lst_repo_info_compare: url_https = repo_info.get("url_https") @@ -671,7 +773,9 @@ class GitTool: name = f"{repo_name}" repo_info["name"] = name - dct_repo_info_compare = {a.get("name"): a for a in lst_repo_info_compare} + dct_repo_info_compare = { + a.get("name"): a for a in lst_repo_info_compare + } set_compare = set(dct_repo_info_compare.keys()) # TODO finish the match @@ -681,16 +785,17 @@ class GitTool: lst_same_name_normalize = set_actual_repo.intersection(set_compare) lst_missing_name_normalize = set_compare.difference(set_actual_repo) lst_over_name_normalize = set_actual_repo.difference(set_compare) - print(f"Has {len(lst_same_name_normalize)} sames, " - f"{len(lst_missing_name_normalize)} missing, " - f"{len(lst_over_name_normalize)} more.") + print( + f"Has {len(lst_same_name_normalize)} sames, " + f"{len(lst_missing_name_normalize)} missing, " + f"{len(lst_over_name_normalize)} more." + ) lst_match = [] for key in lst_same_name_normalize: - lst_match.append(( - dct_repo_info_actual_adapted[key], - dct_repo_info_compare[key] - )) + lst_match.append( + (dct_repo_info_actual_adapted[key], dct_repo_info_compare[key]) + ) return lst_match, lst_missing_name_normalize, lst_over_name_normalize @@ -728,14 +833,18 @@ class GitTool: repo_compare = Repo(compare_to.get("relative_path")) commit_compare = repo_compare.head.object.hexsha if commit_original != commit_compare: - print(f"DIFF - {original.get('name')} - O {commit_original} - " - f"R {commit_compare}") + print( + f"DIFF - {original.get('name')} - O {commit_original} - " + f"R {commit_compare}" + ) lst_diff.append((original, compare_to)) if checkout_when_diff: # Update all remote for remote in repo_original.remotes: - retry(wait_exponential_multiplier=1000, stop_max_delay=15000)( - remote.fetch)() + retry( + wait_exponential_multiplier=1000, + stop_max_delay=15000, + )(remote.fetch)() repo_original.git.checkout(commit_compare) else: print(f"SAME - {original.get('name')}") @@ -743,8 +852,9 @@ class GitTool: print(f"finish same {len(lst_same)}, diff {len(lst_diff)}") @staticmethod - def add_and_fetch_remote(repo_info: Struct, root_repo: Repo = None, - branch_name: str = ""): + def add_and_fetch_remote( + repo_info: Struct, root_repo: Repo = None, branch_name: str = "" + ): """ Deprecated function, not use anymore git submodule :param repo_info: @@ -754,42 +864,57 @@ class GitTool: """ try: working_repo = Repo(repo_info.relative_path) - if repo_info.organization in [a.name for a in working_repo.remotes]: - print(f"Remote \"{repo_info.organization}\" already exist " - f"in {repo_info.relative_path}") + if repo_info.organization in [ + a.name for a in working_repo.remotes + ]: + print( + f'Remote "{repo_info.organization}" already exist ' + f"in {repo_info.relative_path}" + ) return except git.NoSuchPathError: print(f"New repo {repo_info.relative_path}") if not root_repo: - print(f"Missing git repository to root for repo {repo_info.path}") + print( + f"Missing git repository to root for repo {repo_info.path}" + ) return if branch_name: submodule_repo = retry( - wait_exponential_multiplier=1000, - stop_max_delay=15000 - )(root_repo.create_submodule)(repo_info.path, repo_info.path, - url=repo_info.url_https, - branch=branch_name) + wait_exponential_multiplier=1000, stop_max_delay=15000 + )(root_repo.create_submodule)( + repo_info.path, + repo_info.path, + url=repo_info.url_https, + branch=branch_name, + ) else: submodule_repo = retry( - wait_exponential_multiplier=1000, - stop_max_delay=15000 - )(root_repo.create_submodule)(repo_info.path, repo_info.path, - url=repo_info.url_https) + wait_exponential_multiplier=1000, stop_max_delay=15000 + )(root_repo.create_submodule)( + repo_info.path, repo_info.path, url=repo_info.url_https + ) return # Add remote - upstream_remote = retry(wait_exponential_multiplier=1000, stop_max_delay=15000)( - working_repo.create_remote)(repo_info.organization, repo_info.url_https) - print('Remote "%s" created for %s' % ( - repo_info.organization, repo_info.url_https)) + upstream_remote = retry( + wait_exponential_multiplier=1000, stop_max_delay=15000 + )(working_repo.create_remote)( + repo_info.organization, repo_info.url_https + ) + print( + 'Remote "%s" created for %s' + % (repo_info.organization, repo_info.url_https) + ) # Fetch the remote retry(wait_exponential_multiplier=1000, stop_max_delay=15000)( - upstream_remote.fetch)() + upstream_remote.fetch + )() print('Remote "%s" fetched' % repo_info.organization) - def get_pull_request_repo(self, upstream_url: str, github_token: str, - organization_name: str = ""): + def get_pull_request_repo( + self, upstream_url: str, github_token: str, organization_name: str = "" + ): """ :param upstream_url: @@ -802,7 +927,9 @@ class GitTool: # Fork the repo status, user = gh.user.get() - user_name = user['login'] if not organization_name else organization_name + user_name = ( + user["login"] if not organization_name else organization_name + ) status, lst_pull = gh.repos[user_name][parsed_url.repo].pulls.get() if type(lst_pull) is dict: print(f"For url {upstream_url}, got {lst_pull.get('message')}") @@ -812,34 +939,41 @@ class GitTool: print(pull.get("html_url")) return lst_pull - def fork_repo(self, upstream_url: str, github_token: str, - organization_name: str = ""): + def fork_repo( + self, upstream_url: str, github_token: str, organization_name: str = "" + ): # https://developer.github.com/apps/building-integrations/setting-up-and-registering-oauth-apps/about-scopes-for-oauth-apps/ gh = GitHub(token=github_token) parsed_url = parse(upstream_url) # Fork the repo status, user = gh.user.get() - user_name = user['login'] if not organization_name else organization_name + user_name = ( + user["login"] if not organization_name else organization_name + ) status, forked_repo = gh.repos[user_name][parsed_url.repo].get() if status == 404: - status, upstream_repo = ( - gh.repos[parsed_url.owner][parsed_url.repo].get()) + status, upstream_repo = gh.repos[parsed_url.owner][ + parsed_url.repo + ].get() if status == 404: print("Unable to find repo %s" % upstream_url) exit(1) args = {} if organization_name: args["organization"] = organization_name - status, forked_repo = ( - gh.repos[parsed_url.owner][parsed_url.repo].forks.post(**args)) + status, forked_repo = gh.repos[parsed_url.owner][ + parsed_url.repo + ].forks.post(**args) if status == 404: print("Error when forking repo %s" % forked_repo) exit(1) else: - print("Forked %s to %s" % (upstream_url, forked_repo['html_url'])) + print( + "Forked %s to %s" % (upstream_url, forked_repo["html_url"]) + ) elif status == 202: - print("Forked repo %s already exists" % forked_repo['full_name']) + print("Forked repo %s already exists" % forked_repo["full_name"]) elif status != 200: print("Status not supported: %s - %s" % (status, forked_repo)) exit(1) diff --git a/script/git_update_repo.py b/script/git_update_repo.py index 8ceb1cb..fef6edd 100755 --- a/script/git_update_repo.py +++ b/script/git_update_repo.py @@ -6,7 +6,7 @@ import logging from git import Repo # pip install gitpython from retrying import retry # pip install retrying -new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '..')) +new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), "..")) sys.path.append(new_path) from script.git_tool import GitTool @@ -23,13 +23,18 @@ def get_config(): # TODO update description parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, - description='''\ -''', - epilog='''\ -''' + description="""\ +""", + epilog="""\ +""", + ) + parser.add_argument( + "-d", + "--dir", + dest="dir", + default="./", + help="Path of repo to change remote, including submodule.", ) - parser.add_argument('-d', '--dir', dest="dir", default="./", - help="Path of repo to change remote, including submodule.") args = parser.parse_args() return args @@ -38,13 +43,21 @@ def main(): config = get_config() git_tool = GitTool() - lst_repo = git_tool.get_source_repo_addons(repo_path=config.dir, - add_repo_root=False) - lst_repo_organization = [git_tool.get_transformed_repo_info_from_url( - a.get("url"), repo_path=config.dir, get_obj=True, - is_submodule=a.get("is_submodule"), sub_path=a.get("sub_path"), - revision=a.get("revision"), clone_depth=a.get("clone_depth")) - for a in lst_repo] + lst_repo = git_tool.get_source_repo_addons( + repo_path=config.dir, add_repo_root=False + ) + lst_repo_organization = [ + git_tool.get_transformed_repo_info_from_url( + a.get("url"), + repo_path=config.dir, + get_obj=True, + is_submodule=a.get("is_submodule"), + sub_path=a.get("sub_path"), + revision=a.get("revision"), + clone_depth=a.get("clone_depth"), + ) + for a in lst_repo + ] i = 0 total = len(lst_repo) @@ -61,17 +74,22 @@ def main(): # 1. Add remote if not exist try: upstream_remote = git_repo.remote(upstream_name) - print(f'Remote "{upstream_name}" already exists in {repo.relative_path}') + print( + f'Remote "{upstream_name}" already exists in' + f" {repo.relative_path}" + ) except ValueError: upstream_remote = retry( - wait_exponential_multiplier=1000, - stop_max_delay=15000 + wait_exponential_multiplier=1000, stop_max_delay=15000 )(git_repo.create_remote)(upstream_name, repo.url_https) - print('Remote "%s" created for %s' % (upstream_name, repo.url_https)) + print( + 'Remote "%s" created for %s' % (upstream_name, repo.url_https) + ) # 2. Fetch the remote source retry(wait_exponential_multiplier=1000, stop_max_delay=15000)( - upstream_remote.fetch)() + upstream_remote.fetch + )() print('Remote "%s" fetched' % upstream_name) # 3. Rebase actual branch with new branch @@ -99,15 +117,19 @@ def main(): # push try: retry(wait_exponential_multiplier=1000, stop_max_delay=15000)( - git_repo.git.push)(repo.organization, rev) + git_repo.git.push + )(repo.organization, rev) except: - print("Cannot push, maybe need to push force or resolv rebase conflict", - file=sys.stderr) + print( + "Cannot push, maybe need to push force or resolv rebase" + " conflict", + file=sys.stderr, + ) print(f"cd {repo.path}") print(f"git diff ERPLibre/v#.#.#..HEAD") print(f"git push --force {repo.organization} {rev}") print(f"cd -") -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/script/poetry_update.py b/script/poetry_update.py index 0db0774..5352e36 100755 --- a/script/poetry_update.py +++ b/script/poetry_update.py @@ -9,7 +9,7 @@ from collections import OrderedDict, defaultdict from pathlib import Path import iscompatible -new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '..')) +new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), "..")) sys.path.append(new_path) from script import git_tool @@ -27,29 +27,45 @@ def get_config(): parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, - description='''\ + description="""\ Update pip dependency in Poetry, clear pyproject.toml, search all dependencies from requirements.txt, search conflict version and generate a new list. Launch Poetry installation. -''', - epilog='''\ -''' +""", + epilog="""\ +""", + ) + parser.add_argument( + "-d", + "--dir", + dest="dir", + default="./", + help="Path of repo to change remote, including submodule.", + ) + parser.add_argument( + "-f", + "--force", + action="store_true", + help="Force create new list of dependency, ignore poetry.lock.", + ) + parser.add_argument( + "-v", + "--verbose", + action="store_true", + help="More information in execution, show stats.", ) - parser.add_argument('-d', '--dir', dest="dir", default="./", - help="Path of repo to change remote, including submodule.") - parser.add_argument('-f', '--force', action="store_true", - help="Force create new list of dependency, ignore poetry.lock.") - parser.add_argument('-v', '--verbose', action="store_true", - help="More information in execution, show stats.") args = parser.parse_args() return args def get_lst_requirements_txt(): # Ignore some item in list - lst = [a for a in Path(".").rglob("requirements.[tT][xX][tT]") - if not os.path.dirname(a).startswith('.repo/') and not os.path.dirname(a).startswith('.venv/') - ] + lst = [ + a + for a in Path(".").rglob("requirements.[tT][xX][tT]") + if not os.path.dirname(a).startswith(".repo/") + and not os.path.dirname(a).startswith(".venv/") + ] return lst @@ -76,7 +92,7 @@ def combine_requirements(config): dct_special_condition = defaultdict(list) dct_requirements_module_filename = defaultdict(list) for requirements_filename in lst_requirements_file: - with open(requirements_filename, 'r') as f: + with open(requirements_filename, "r") as f: for a in f.readlines(): b = a.strip() if not b or b[0] == "#": @@ -86,10 +102,14 @@ def combine_requirements(config): for sign in lst_sign: if sign in b: # Exception, some time the sign ; can be first, just check - if sign != ";" and ";" in b and b.find(sign) > b.find(";"): - module_name = b[:b.find(";")] + if ( + sign != ";" + and ";" in b + and b.find(sign) > b.find(";") + ): + module_name = b[: b.find(";")] else: - module_name = b[:b.find(sign)] + module_name = b[: b.find(sign)] module_name = module_name.strip() # Special condition for ";", ignore it if ";" in b: @@ -99,13 +119,15 @@ def combine_requirements(config): if ignore_string in b: break lst_requirements_with_condition.add(module_name) - value = b[:b.find(";")].strip() + value = b[: b.find(";")].strip() dct_special_condition[module_name].append(b) else: value = b dct_requirements[module_name].add(value) filename = str(requirements_filename) - dct_requirements_module_filename[value].append(filename) + dct_requirements_module_filename[value].append( + filename + ) break else: dct_requirements[b].add(b) @@ -115,16 +137,19 @@ def combine_requirements(config): dct_requirements = get_manifest_external_dependencies(dct_requirements) - dct_requirements_diff_version = {k: v for k, v in dct_requirements.items() if - len(v) > 1} + dct_requirements_diff_version = { + k: v for k, v in dct_requirements.items() if len(v) > 1 + } # dct_requirements_same_version = {k: v for k, v in dct_requirements.items() if # len(v) == 1} if config.verbose: # TODO show total repo to compare lst requirements - print(f"Total requirements.txt {len(lst_requirements_file)}, " - f"total module {len(lst_requirements)}, " - f"unique module {len(dct_requirements)}, " - f"module with different version {len(dct_requirements_diff_version)}.") + print( + f"Total requirements.txt {len(lst_requirements_file)}, total" + f" module {len(lst_requirements)}, unique module" + f" {len(dct_requirements)}, module with different version" + f" {len(dct_requirements_diff_version)}." + ) if dct_requirements_diff_version: # Validate compatibility @@ -143,20 +168,29 @@ def combine_requirements(config): # TODO support me in iscompatible lib no_version = result_number[0][1] if "b" in no_version: - result_number[0] = result_number[0][0], no_version[ - :no_version.find("b")] - elif not no_version[no_version.rfind(".") + 1:].isnumeric(): - result_number[0] = result_number[0][0], no_version[ - :no_version.rfind(".")] - result_number = iscompatible.string_to_tuple(result_number[0][1]) + result_number[0] = ( + result_number[0][0], + no_version[: no_version.find("b")], + ) + elif not no_version[no_version.rfind(".") + 1 :].isnumeric(): + result_number[0] = ( + result_number[0][0], + no_version[: no_version.rfind(".")], + ) + result_number = iscompatible.string_to_tuple( + result_number[0][1] + ) lst_version_requirement.append((requirement, result_number)) # Check compatibility with all possibility is_compatible = True if len(lst_version_requirement) > 1: - highest_value = sorted(lst_version_requirement, key=lambda tup: tup[1])[-1] + highest_value = sorted( + lst_version_requirement, key=lambda tup: tup[1] + )[-1] for version_requirement in lst_version_requirement: - is_compatible &= iscompatible.iscompatible(version_requirement[0], - highest_value[1]) + is_compatible &= iscompatible.iscompatible( + version_requirement[0], highest_value[1] + ) if is_compatible: result = highest_value[0] else: @@ -166,26 +200,39 @@ def combine_requirements(config): erplibre_value = None for version_requirement in lst_version_requirement: filename_1 = dct_requirements_module_filename.get( - version_requirement[0]) + version_requirement[0] + ) if priority_filename_requirement in filename_1: erplibre_value = version_requirement[0] - elif second_priority_filename_requirement in filename_1: + elif ( + second_priority_filename_requirement in filename_1 + ): odoo_value = version_requirement[0] if erplibre_value: - str_result_choose = f"Select {erplibre_value} because from ERPLibre" + str_result_choose = ( + f"Select {erplibre_value} because from ERPLibre" + ) result = erplibre_value elif odoo_value: - str_result_choose = f"Select {odoo_value} because from Odoo" + str_result_choose = ( + f"Select {odoo_value} because from Odoo" + ) result = odoo_value else: result = highest_value[0] str_result_choose = f"Select highest value {result}" str_versions = " VS ".join( - [f"{a[0]} from {dct_requirements_module_filename.get(a[0])}" for - a in lst_version_requirement]) - print(f"WARNING - Not compatible {str_versions} - " - f"{str_result_choose}.") + [ + f"{a[0]} from" + f" {dct_requirements_module_filename.get(a[0])}" + for a in lst_version_requirement + ] + ) + print( + f"WARNING - Not compatible {str_versions} - " + f"{str_result_choose}." + ) elif len(lst_version_requirement) == 1: result = lst_version_requirement[0][0] else: @@ -206,13 +253,13 @@ def combine_requirements(config): for key in lst_ignored_key: del dct_requirements[key] - with open("./.venv/build_dependency.txt", 'w') as f: + with open("./.venv/build_dependency.txt", "w") as f: f.writelines([f"{list(a)[0]}\n" for a in dct_requirements.values()]) def sorted_dependency_poetry(pyproject_filename): # Open pyproject.toml - with open(pyproject_filename, 'r') as f: + with open(pyproject_filename, "r") as f: dct_pyproject = toml.load(f) # Get dependencies and update list, sorted @@ -222,19 +269,23 @@ def sorted_dependency_poetry(pyproject_filename): poetry = tool.get("poetry") if poetry: dependencies = poetry.get("dependencies") - python_dependency = ("python", dependencies.get("python", '')) - lst_dependency = [(k, v) for k, v in dependencies.items() if k != "python"] + python_dependency = ("python", dependencies.get("python", "")) + lst_dependency = [ + (k, v) for k, v in dependencies.items() if k != "python" + ] lst_dependency = sorted(lst_dependency, key=lambda tup: tup[0]) - poetry["dependencies"] = OrderedDict([python_dependency] + lst_dependency) + poetry["dependencies"] = OrderedDict( + [python_dependency] + lst_dependency + ) # Rewrite pyproject.toml - with open(pyproject_filename, 'w') as f: + with open(pyproject_filename, "w") as f: toml.dump(dct_pyproject, f) def delete_dependency_poetry(pyproject_filename): # Open pyproject.toml - with open(pyproject_filename, 'r') as f: + with open(pyproject_filename, "r") as f: dct_pyproject = toml.load(f) # Get dependencies and update list, sorted @@ -244,11 +295,11 @@ def delete_dependency_poetry(pyproject_filename): poetry = tool.get("poetry") if poetry: dependencies = poetry.get("dependencies") - python_dependency = ("python", dependencies.get("python", '')) + python_dependency = ("python", dependencies.get("python", "")) poetry["dependencies"] = OrderedDict([python_dependency]) # Rewrite pyproject.toml - with open(pyproject_filename, 'w') as f: + with open(pyproject_filename, "w") as f: toml.dump(dct_pyproject, f) @@ -256,7 +307,7 @@ def get_manifest_external_dependencies(dct_requirements): lst_manifest_file = get_lst_manifest_py() lst_dct_ext_depend = [] for manifest_file in lst_manifest_file: - with open(manifest_file, 'r') as f: + with open(manifest_file, "r") as f: contents = f.read() try: dct = ast.literal_eval(contents) @@ -289,7 +340,7 @@ def call_poetry_add_build_dependency(): def get_list_ignored(): - with open("./ignore_requirements.txt", 'r') as f: + with open("./ignore_requirements.txt", "r") as f: lst_ignore_requirements = [a.strip() for a in f.readlines()] return lst_ignore_requirements @@ -298,7 +349,7 @@ def main(): # repo = Repo(root_path) # lst_repo = get_all_repo() config = get_config() - pyproject_toml_filename = f'{config.dir}pyproject.toml' + pyproject_toml_filename = f"{config.dir}pyproject.toml" delete_dependency_poetry(pyproject_toml_filename) combine_requirements(config) @@ -309,5 +360,5 @@ def main(): sorted_dependency_poetry(pyproject_toml_filename) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/script/pull_request_ERPLibre.py b/script/pull_request_ERPLibre.py index 055e73b..eee235b 100755 --- a/script/pull_request_ERPLibre.py +++ b/script/pull_request_ERPLibre.py @@ -4,7 +4,7 @@ import sys import argparse import logging -new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '..')) +new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), "..")) sys.path.append(new_path) from script.git_tool import GitTool @@ -24,18 +24,30 @@ def get_config(): # TODO update description parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, - description='''\ -''', - epilog='''\ -''' + description="""\ +""", + epilog="""\ +""", + ) + parser.add_argument( + "-d", + "--dir", + dest="dir", + default="./", + help="Path of repo to change remote, including submodule.", + ) + parser.add_argument( + "--organization", + dest="organization", + default="ERPLibre", + help="Choose organization to fork and change all repo.", + ) + parser.add_argument( + "--github_token", + dest="github_token", + default=config.get(CST_EL_GITHUB_TOKEN), + help="GitHub token generated by user", ) - parser.add_argument('-d', '--dir', dest="dir", default="./", - help="Path of repo to change remote, including submodule.") - parser.add_argument('--organization', dest="organization", default="ERPLibre", - help="Choose organization to fork and change all repo.") - parser.add_argument('--github_token', dest="github_token", - default=config.get(CST_EL_GITHUB_TOKEN), - help="GitHub token generated by user") args = parser.parse_args() return args @@ -49,12 +61,21 @@ def main(): raise ValueError("Missing github_token") organization_name = config.organization - lst_repo = git_tool.get_source_repo_addons(repo_path=config.dir, add_repo_root=True) - lst_repo_organization = [git_tool.get_transformed_repo_info_from_url( - a.get("url"), repo_path=config.dir, organization_force=organization_name, - is_submodule=a.get("is_submodule"), sub_path=a.get("sub_path"), - revision=a.get("revision"), clone_depth=a.get("clone_depth")) - for a in lst_repo] + lst_repo = git_tool.get_source_repo_addons( + repo_path=config.dir, add_repo_root=True + ) + lst_repo_organization = [ + git_tool.get_transformed_repo_info_from_url( + a.get("url"), + repo_path=config.dir, + organization_force=organization_name, + is_submodule=a.get("is_submodule"), + sub_path=a.get("sub_path"), + revision=a.get("revision"), + clone_depth=a.get("clone_depth"), + ) + for a in lst_repo + ] url_not_found_count = 0 url_found_count = 0 @@ -66,9 +87,11 @@ def main(): print(f"Nb element {i}/{total} - {repo.project_name}") url = repo.url - status = git_tool.get_pull_request_repo(upstream_url=url, - github_token=github_token, - organization_name=organization_name) + status = git_tool.get_pull_request_repo( + upstream_url=url, + github_token=github_token, + organization_name=organization_name, + ) if status is False: url_not_found_count += 1 else: @@ -78,5 +101,5 @@ def main(): print(f"URL found: {url_found_count}") -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/script/repo_remove_auto_install.py b/script/repo_remove_auto_install.py index 0c5ef88..4e40a88 100755 --- a/script/repo_remove_auto_install.py +++ b/script/repo_remove_auto_install.py @@ -7,7 +7,7 @@ from pathlib import Path from git import Repo # pip install gitpython from git.exc import GitCommandError -new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '..')) +new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), "..")) sys.path.append(new_path) from script.git_tool import GitTool @@ -24,13 +24,18 @@ def get_config(): # TODO update description parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, - description='''\ -''', - epilog='''\ -''' + description="""\ +""", + epilog="""\ +""", + ) + parser.add_argument( + "-d", + "--dir", + dest="dir", + default="./", + help="Path of repo to change remote, including submodule.", ) - parser.add_argument('-d', '--dir', dest="dir", default="./", - help="Path of repo to change remote, including submodule.") args = parser.parse_args() return args @@ -39,13 +44,21 @@ def main(): config = get_config() git_tool = GitTool() - lst_repo = git_tool.get_source_repo_addons(repo_path=config.dir, - add_repo_root=False) - lst_repo_organization = [git_tool.get_transformed_repo_info_from_url( - a.get("url"), repo_path=config.dir, get_obj=True, - is_submodule=a.get("is_submodule"), sub_path=a.get("sub_path"), - revision=a.get("revision"), clone_depth=a.get("clone_depth")) - for a in lst_repo] + lst_repo = git_tool.get_source_repo_addons( + repo_path=config.dir, add_repo_root=False + ) + lst_repo_organization = [ + git_tool.get_transformed_repo_info_from_url( + a.get("url"), + repo_path=config.dir, + get_obj=True, + is_submodule=a.get("is_submodule"), + sub_path=a.get("sub_path"), + revision=a.get("revision"), + clone_depth=a.get("clone_depth"), + ) + for a in lst_repo + ] lst_ignore_repo = ["odoo"] @@ -68,7 +81,9 @@ def main(): is_checkout_branch = True except GitCommandError: try: - git_repo.git.checkout("-t", f"{repo.organization}/{branch_name}") + git_repo.git.checkout( + "-t", f"{repo.organization}/{branch_name}" + ) is_checkout_branch = True except GitCommandError: pass @@ -93,7 +108,7 @@ def get_manifest_external_dependencies(repo): lst_manifest_file = get_lst_manifest_py(repo.relative_path) for manifest_file in lst_manifest_file: has_change_manifest = False - with open(manifest_file, 'r') as f: + with open(manifest_file, "r") as f: lst_content = f.readlines() i = 0 for content in lst_content: @@ -102,16 +117,18 @@ def get_manifest_external_dependencies(repo): has_change = True first_char_index = content.find("auto_install") index = content.find("True", first_char_index) - lst_content[i] = content[:index] + "False" + content[index + 4:] + lst_content[i] = ( + content[:index] + "False" + content[index + 4 :] + ) i += 1 if has_change_manifest: print(f"Update file {manifest_file}") - with open(manifest_file, 'w') as f: + with open(manifest_file, "w") as f: f.writelines(lst_content) return has_change -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/script/repo_revert_git_diff_date_from_code_generator.py b/script/repo_revert_git_diff_date_from_code_generator.py index 7318a5d..85c892a 100755 --- a/script/repo_revert_git_diff_date_from_code_generator.py +++ b/script/repo_revert_git_diff_date_from_code_generator.py @@ -7,7 +7,7 @@ import git from unidiff import PatchSet import re -new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '..')) +new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), "..")) sys.path.append(new_path) _logger = logging.getLogger(__name__) @@ -22,10 +22,10 @@ def get_config(): # TODO update description parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, - description='''\ -''', - epilog='''\ -''' + description="""\ +""", + epilog="""\ +""", ) args = parser.parse_args() return args @@ -34,7 +34,10 @@ def get_config(): def main(): config = get_config() # rex = r"\s+(?=\d{2}(?:\d{2})?-\d{1,2}-\d{1,2}\b)" - rex = r"[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) (2[0-3]|[01][0-9]):[0-5][0-9]" + rex = ( + r"[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])" + r" (2[0-3]|[01][0-9]):[0-5][0-9]" + ) # TODO support argument instead of hardcoded values lst_path = [ "./addons/TechnoLibre_odoo-code-generator-template", @@ -56,7 +59,7 @@ def main(): is_modified = False lst_write_data = [] # Delete code expression path caused by ERPLibre architecture - with open(file_real_path, 'r') as file: + with open(file_real_path, "r") as file: lst_data = file.readlines() for data in lst_data: if data.startswith("#: code:addons/addons/"): @@ -64,7 +67,7 @@ def main(): else: lst_write_data.append(data) if is_modified: - with open(file_real_path, 'w') as file: + with open(file_real_path, "w") as file: file.writelines(lst_write_data) str_diff = repo.git.diff(diff.a_path) @@ -76,7 +79,10 @@ def main(): nb_line_target = len(hunk.target) if nb_line_source != nb_line_target: # TODO support different line - _logger.warning(f"Source nb line different of target nb line for file {path}/{file_path}.") + _logger.warning( + "Source nb line different of target nb line" + f" for file {path}/{file_path}." + ) continue # try: # assert nb_line_source == nb_line_target, f"Not the same line of diff:\n{str_diff}" @@ -88,22 +94,27 @@ def main(): result_target = re.split(rex, hunk.target[i]) else: result_target = "" - if len(result_source) > 1 or len(result_target) > 1: + if ( + len(result_source) > 1 + or len(result_target) > 1 + ): line_to_change = hunk.target_start + i - 1 - lst_to_write.append((line_to_change, hunk.source[i][1:])) + lst_to_write.append( + (line_to_change, hunk.source[i][1:]) + ) # rewrite rewrite(file_real_path, lst_to_write) def rewrite(file_path, lst_to_write): # TODO not optimal for big file - with open(file_path, 'r') as file: + with open(file_path, "r") as file: data = file.readlines() for line in lst_to_write: data[line[0]] = line[1] - with open(file_path, 'w') as file: + with open(file_path, "w") as file: file.writelines(data) -if __name__ == '__main__': +if __name__ == "__main__": main() From 702f4191198bedb7d7d0f3017fe0f663aa6c0afc Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Sun, 27 Jun 2021 01:24:31 -0400 Subject: [PATCH 39/44] [UPD] code_generator need --dev to be installed for secure in prod --- Makefile | 36 +++++++++---------- doc/CODE_GENERATOR.base.md | 20 +++++------ script/addons/install_addons_dev.sh | 7 ++++ script/addons/reinstall_addons.sh | 2 +- .../install_and_test_code_generator.sh | 4 +-- 5 files changed, 38 insertions(+), 31 deletions(-) create mode 100755 script/addons/install_addons_dev.sh diff --git a/Makefile b/Makefile index 9d91ea4..58ce9f4 100644 --- a/Makefile +++ b/Makefile @@ -144,19 +144,19 @@ db_restore_erplibre_base_db_template: ######################### .PHONY: addons_install_code_generator_basic addons_install_code_generator_basic: db_restore_erplibre_base_db_code_generator - ./script/addons/install_addons.sh code_generator code_generator + ./script/addons/install_addons_dev.sh code_generator code_generator .PHONY: addons_install_code_generator_featured addons_install_code_generator_featured: addons_install_code_generator_basic - ./script/addons/install_addons.sh code_generator code_generator_cron,code_generator_hook,code_generator_portal + ./script/addons/install_addons_dev.sh code_generator code_generator_cron,code_generator_hook,code_generator_portal .PHONY: addons_install_code_generator_full addons_install_code_generator_full: addons_install_code_generator_featured - ./script/addons/install_addons.sh code_generator code_generator_db_servers,code_generator_website_snippet,code_generator_geoengine,code_generator_theme_website,code_generator_website_leaflet + ./script/addons/install_addons_dev.sh code_generator code_generator_db_servers,code_generator_website_snippet,code_generator_geoengine,code_generator_theme_website,code_generator_website_leaflet .PHONY: addons_install_code_generator_demo addons_install_code_generator_demo: - ./script/addons/install_addons.sh code_generator code_generator_demo + ./script/addons/install_addons_dev.sh code_generator code_generator_demo .PHONY: addons_uninstall_code_generator_demo addons_uninstall_code_generator_demo: @@ -167,28 +167,28 @@ addons_reinstall_code_generator_demo: addons_uninstall_code_generator_demo addon .PHONY: addons_install_all_code_generator_demo addons_install_all_code_generator_demo: db_restore_erplibre_base_db_code_generator - ./script/addons/install_addons.sh code_generator code_generator_demo - ./script/addons/install_addons.sh code_generator code_generator_demo_export_helpdesk - ./script/addons/install_addons.sh code_generator code_generator_demo_internal - ./script/addons/install_addons.sh code_generator code_generator_demo_portal - ./script/addons/install_addons.sh code_generator code_generator_demo_theme_website - ./script/addons/install_addons.sh code_generator code_generator_demo_website_leaflet - ./script/addons/install_addons.sh code_generator code_generator_demo_website_snippet + ./script/addons/install_addons_dev.sh code_generator code_generator_demo + ./script/addons/install_addons_dev.sh code_generator code_generator_demo_export_helpdesk + ./script/addons/install_addons_dev.sh code_generator code_generator_demo_internal + ./script/addons/install_addons_dev.sh code_generator code_generator_demo_portal + ./script/addons/install_addons_dev.sh code_generator code_generator_demo_theme_website + ./script/addons/install_addons_dev.sh code_generator code_generator_demo_website_leaflet + ./script/addons/install_addons_dev.sh code_generator code_generator_demo_website_snippet .PHONY: addons_install_all_code_generator_template addons_install_all_code_generator_template: - ./script/addons/install_addons.sh template demo_portal,auto_backup - ./script/addons/install_addons.sh template code_generator_template_demo_portal code_generator_template_demo_sysadmin_cron + ./script/addons/install_addons_dev.sh template demo_portal,auto_backup + ./script/addons/install_addons_dev.sh template code_generator_template_demo_portal code_generator_template_demo_sysadmin_cron .PHONY: addons_install_all_generated_demo addons_install_all_generated_demo: - ./script/addons/install_addons.sh template demo_export_helpdesk,demo_internal,demo_portal,demo_website_leaflet,demo_website_snippet + ./script/addons/install_addons_dev.sh template demo_export_helpdesk,demo_internal,demo_portal,demo_website_leaflet,demo_website_snippet # TODO support installation theme with cli - #./script/addons/install_addons.sh template theme_website_demo_code_generator + #./script/addons/install_addons_dev.sh template theme_website_demo_code_generator .PHONY: addons_install_all_code_generator addons_install_all_code_generator: - ./script/addons/install_addons.sh code_generator code_generator_auto_backup + ./script/addons/install_addons_dev.sh code_generator code_generator_auto_backup ########## # test # @@ -223,14 +223,14 @@ test_code_generator_generation_extra: test_code_generator_code_i18n: ./script/code_generator/check_git_change_code_generator.sh ./addons/TechnoLibre_odoo-code-generator-template time ./script/db_restore.py --database template - ./script/addons/install_addons.sh template demo_portal + ./script/addons/install_addons_dev.sh template demo_portal ./script/code_generator/install_and_test_code_generator.sh template code_generator_template_demo_portal ./addons/TechnoLibre_odoo-code-generator-template .PHONY: test_code_generator_code_i18n_extra test_code_generator_code_i18n_extra: ./script/code_generator/check_git_change_code_generator.sh ./addons/OCA_server-tools/auto_backup time ./script/db_restore.py --database template - ./script/addons/install_addons.sh template auto_backup + ./script/addons/install_addons_dev.sh template auto_backup ./script/code_generator/install_and_test_code_generator.sh template code_generator_template_demo_sysadmin_cron ./addons/TechnoLibre_odoo-code-generator-template # To support i18n in auto_backup ./script/code_generator/check_git_change_code_generator.sh ./addons/OCA_server-tools/auto_backup diff --git a/doc/CODE_GENERATOR.base.md b/doc/CODE_GENERATOR.base.md index 667d800..6d10a83 100644 --- a/doc/CODE_GENERATOR.base.md +++ b/doc/CODE_GENERATOR.base.md @@ -218,7 +218,7 @@ Pour continuer avec l'exemple, généré le template `code_generator_template_de ```bash make db_restore_erplibre_base_db_template -./script/addons/install_addons.sh template code_generator_template_demo_website_snippet +./script/addons/install_addons_dev.sh template code_generator_template_demo_website_snippet ``` @@ -259,7 +259,7 @@ Pour continuer avec l'exemple, généré le template `code_generator_template_de ```bash -./script/addons/install_addons.sh code_generator code_generator_template_demo_website_snippet +./script/addons/install_addons_dev.sh code_generator code_generator_template_demo_website_snippet ``` @@ -293,7 +293,7 @@ Générer votre module : ```bash -./script/addons/install_addons.sh code_generator code_generator_demo_website_snippet +./script/addons/install_addons_dev.sh code_generator code_generator_demo_website_snippet ``` @@ -311,7 +311,7 @@ Il est maintenant possible de modifier les paramètres via l'interface manuelle ```bash make db_restore_erplibre_base_db_code_generator -./script/addons/install_addons.sh code_generator code_generator_demo_website_snippet +./script/addons/install_addons_dev.sh code_generator code_generator_demo_website_snippet ``` @@ -332,7 +332,7 @@ value["enable_sync_template"] = True Exécuter l'installation du template pour qu'il se synchronise sur le module généré. ```bash make db_restore_erplibre_base_db_template -./script/addons/install_addons.sh template code_generator_template_demo_website_snippet +./script/addons/install_addons_dev.sh template code_generator_template_demo_website_snippet ``` @@ -345,7 +345,7 @@ Prêt à tester, générer le module : ```bash # Optional, reset test database make db_restore_erplibre_base_db_test -./script/addons/install_addons.sh test demo_website_snippet +./script/addons/install_addons_dev.sh test demo_website_snippet ``` @@ -375,8 +375,8 @@ Premièrement, installer le module, par exemple `demo_portal`, et ensuite le tem ```bash make db_restore_erplibre_base_db_code_generator -./script/addons/install_addons.sh test demo_portal -./script/addons/install_addons.sh test code_generator_template_demo_portal +./script/addons/install_addons_dev.sh test demo_portal +./script/addons/install_addons_dev.sh test code_generator_template_demo_portal ``` @@ -403,8 +403,8 @@ Exemple : ```bash make db_restore_erplibre_base_db_code_generator -./script/addons/install_addons.sh test demo_portal -./script/addons/install_addons.sh test code_generator_template_demo_portal +./script/addons/install_addons_dev.sh test demo_portal +./script/addons/install_addons_dev.sh test code_generator_template_demo_portal ``` diff --git a/script/addons/install_addons_dev.sh b/script/addons/install_addons_dev.sh new file mode 100755 index 0000000..ba82bb8 --- /dev/null +++ b/script/addons/install_addons_dev.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +./run.sh --no-http --stop-after-init --dev qweb -d $1 -i $2 -u $2 +retVal=$? +if [[ $retVal -ne 0 ]]; then + echo "Error install_addons_dev.sh" + exit 1 +fi diff --git a/script/addons/reinstall_addons.sh b/script/addons/reinstall_addons.sh index 4035d72..a32fb6e 100755 --- a/script/addons/reinstall_addons.sh +++ b/script/addons/reinstall_addons.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash ./script/addons/uninstall_addons.sh $1 $2 -./script/addons/install_addons.sh $1 $2 +./script/addons/install_addons_dev.sh $1 $2 retVal=$? if [[ $retVal -ne 0 ]]; then echo "Error reinstall_addons.sh" diff --git a/script/code_generator/install_and_test_code_generator.sh b/script/code_generator/install_and_test_code_generator.sh index 9290906..58f66bb 100755 --- a/script/code_generator/install_and_test_code_generator.sh +++ b/script/code_generator/install_and_test_code_generator.sh @@ -3,10 +3,10 @@ # $2 is module name # $3 is directory path to check -./script/addons/install_addons.sh $1 $2 +./script/addons/install_addons_dev.sh $1 $2 retVal=$? if [[ $retVal -ne 0 ]]; then - echo "Error ./script/addons/install_addons.sh ${1} ${2}" + echo "Error ./script/addons/install_addons_dev.sh ${1} ${2}" exit 1 fi ./script/repo_revert_git_diff_date_from_code_generator.py From f7d70086fdf779c081d820ecbde730372db9a21a Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Sun, 27 Jun 2021 16:51:30 -0400 Subject: [PATCH 40/44] [FIX] docker build, update dependencies and fix poetry - Use image with python 3.7.7 instead of using pyenv --- docker/Dockerfile.base | 47 +++++++-------------- docker/Dockerfile.prod.pkg | 17 +++++++- docker/repo_manifest_gen_org_prefix_path.py | 2 +- 3 files changed, 32 insertions(+), 34 deletions(-) diff --git a/docker/Dockerfile.base b/docker/Dockerfile.base index 3f992b8..f6e408a 100644 --- a/docker/Dockerfile.base +++ b/docker/Dockerfile.base @@ -1,4 +1,4 @@ -FROM debian:buster-slim +FROM python:3.7.7-slim-buster MAINTAINER TechnoLibre SHELL ["/bin/bash", "-xo", "pipefail", "-c"] @@ -25,29 +25,19 @@ RUN apt-get update \ gnupg \ libssl-dev \ npm \ - python3-num2words \ - python3-pip \ - python3-phonenumbers \ - python3-pyldap \ - python3-qrcode \ - python3-renderpm \ - python3-setuptools \ - python3-slugify \ - python3-vobject \ - python3-watchdog \ - python3-xlrd \ - python3-xlwt \ - python3-babel \ - python3-psycopg2 \ xz-utils \ git \ wget \ + make \ + libssl-dev \ + zlib1g-dev \ + llvm \ + tk-dev \ libxslt-dev \ libzip-dev \ libldap2-dev \ libsasl2-dev \ gdebi-core \ - libffi-dev \ iproute2 \ libmariadbd-dev \ inetutils-ping \ @@ -85,21 +75,21 @@ RUN echo 'deb http://apt.postgresql.org/pub/repos/apt/ buster-pgdg main' > /etc/ && rm -rf /var/lib/apt/lists/* # Install npm dependencies -RUN npm install -g rtlcss less \ +RUN npm install -g rtlcss less prettier @prettier/plugin-xml \ && ln -fs /usr/local/bin/lessc /usr/bin/lessc # Install python with pyenv # Reference https://github.com/bopen/docker-ubuntu-pyenv -COPY pyenv-version.txt python-versions.txt / +#COPY pyenv-version.txt python-versions.txt / -RUN git clone -b `cat /pyenv-version.txt` --single-branch --depth 1 https://github.com/pyenv/pyenv.git $PYENV_ROOT \ - && for version in `cat /python-versions.txt`; do pyenv install $version; done \ - && pyenv global `cat /python-versions.txt` \ - && find $PYENV_ROOT/versions -type d '(' -name '__pycache__' -o -name 'test' -o -name 'tests' ')' -exec rm -rf '{}' + \ - && find $PYENV_ROOT/versions -type f '(' -name '*.pyo' -o -name '*.exe' ')' -exec rm -f '{}' + \ - && rm -rf /tmp/* \ - && python --version \ - && python3 --version +#RUN git clone -b `cat /pyenv-version.txt` --single-branch --depth 1 https://github.com/pyenv/pyenv.git $PYENV_ROOT \ +# && for version in `cat /python-versions.txt`; do pyenv install $version; done \ +# && pyenv global `cat /python-versions.txt` \ +# && find $PYENV_ROOT/versions -type d '(' -name '__pycache__' -o -name 'test' -o -name 'tests' ')' -exec rm -rf '{}' + \ +# && find $PYENV_ROOT/versions -type f '(' -name '*.pyo' -o -name '*.exe' ')' -exec rm -f '{}' + \ +# && rm -rf /tmp/* \ +# && python --version \ +# && python3 --version # Install git-repo RUN cd ; mkdir -p .bin/ && \ @@ -112,11 +102,6 @@ RUN cd ; mkdir -p .bin/ && \ RUN groupadd --gid 101 --force odoo && \ useradd --non-unique --create-home --uid 101 --gid 101 odoo -# TODO delete poetry installation -# Install Poetry -RUN curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python - -y --preview --version 1.0.10 -#curl -fsS -o get-poetry.py https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py - # Copy entrypoint script and Odoo configuration file COPY ./entrypoint.sh / RUN chmod +x /entrypoint.sh diff --git a/docker/Dockerfile.prod.pkg b/docker/Dockerfile.prod.pkg index f9a3c30..9706f67 100644 --- a/docker/Dockerfile.prod.pkg +++ b/docker/Dockerfile.prod.pkg @@ -34,9 +34,22 @@ RUN cd $ODOO_PREFIX && \ RUN cd $ODOO_PREFIX && \ ./script/update_manifest_dev.sh +# TODO delete poetry installation +# Install Poetry RUN cd $ODOO_PREFIX && \ - source /root/.poetry/env && \ - poetry install + curl -sSL -o get-poetry.py https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py && \ + ./.venv/bin/python get-poetry.py -y --preview --version 1.0.10 + +RUN cd $ODOO_PREFIX && \ + ./.venv/bin/pip install --upgrade pip && \ + ./.venv/bin/python ~/.poetry/bin/poetry install && \ + rm -rf artifacts + +RUN cd $ODOO_PREFIX/.venv && \ + curl https://raw.githubusercontent.com/ERPLibre/multilingual-markdown/master/multilang_md.py > ./multilang_md.py && \ + chmod +x ./multilang_md.py && \ + sed -i 1d ./multilang_md.py && \ + sed -i "1 i #!./.venv/bin/python" ./multilang_md.py RUN cd $ODOO_PREFIX && \ head /etc/odoo/odoo.conf && \ diff --git a/docker/repo_manifest_gen_org_prefix_path.py b/docker/repo_manifest_gen_org_prefix_path.py index 7838e11..01b323a 100755 --- a/docker/repo_manifest_gen_org_prefix_path.py +++ b/docker/repo_manifest_gen_org_prefix_path.py @@ -25,7 +25,7 @@ addonsDirs = [abspath(join(addonsBaseDir, f)) for f in listdir(addonsBaseDir) if # addonsDirs.insert(0, "/usr/lib/python3/dist-packages/odoo/addons/") # TODO path addons/addons is not exist in docker, so force to add it -addonsDirs.insert(0, "/ERPLibre/addons/addons") +# addonsDirs.insert(0, "/ERPLibre/addons/addons") addonsDirs.insert(0, "/ERPLibre/odoo/addons/") config = configparser.ConfigParser() From 85c8c87253f77be4eb314bce61bf3829cdd2c8fd Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Mon, 28 Jun 2021 04:57:19 -0400 Subject: [PATCH 41/44] [REM] time in makefile, use it externaly --- Makefile | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 58ce9f4..de5776c 100644 --- a/Makefile +++ b/Makefile @@ -101,43 +101,43 @@ db_drop_db_test3: .PHONY: db_drop_db_code_generator db_drop_db_code_generator: - time ./.venv/bin/python3 ./odoo/odoo-bin db --drop --database code_generator + ./.venv/bin/python3 ./odoo/odoo-bin db --drop --database code_generator .PHONY: db_drop_db_template db_drop_db_template: - time ./.venv/bin/python3 ./odoo/odoo-bin db --drop --database template + ./.venv/bin/python3 ./odoo/odoo-bin db --drop --database template .PHONY: db_restore_erplibre_base_db_test db_restore_erplibre_base_db_test: - time ./script/db_restore.py --database test + ./script/db_restore.py --database test .PHONY: db_restore_erplibre_base_db_test2 db_restore_erplibre_base_db_test2: - time ./script/db_restore.py --database test2 + ./script/db_restore.py --database test2 .PHONY: db_restore_erplibre_base_db_test3 db_restore_erplibre_base_db_test3: - time ./script/db_restore.py --database test3 + ./script/db_restore.py --database test3 .PHONY: db_restore_erplibre_website_db_test db_restore_erplibre_website_db_test: - time ./script/db_restore.py --database test --image erplibre_website + ./script/db_restore.py --database test --image erplibre_website .PHONY: db_restore_erplibre_website_chat_crm_db_test db_restore_erplibre_website_chat_crm_db_test: - time ./script/db_restore.py --database test --image erplibre_website_chat_crm + ./script/db_restore.py --database test --image erplibre_website_chat_crm .PHONY: db_restore_erplibre_ecommerce_base_db_test db_restore_erplibre_ecommerce_base_db_test: - time ./script/db_restore.py --database test --image erplibre_ecommerce_base + ./script/db_restore.py --database test --image erplibre_ecommerce_base .PHONY: db_restore_erplibre_base_db_code_generator db_restore_erplibre_base_db_code_generator: - time ./script/db_restore.py --database code_generator + ./script/db_restore.py --database code_generator .PHONY: db_restore_erplibre_base_db_template db_restore_erplibre_base_db_template: - time ./script/db_restore.py --database template + ./script/db_restore.py --database template ######################### # Addons installation # @@ -204,7 +204,7 @@ test_format: .PHONY: test_code_generator_generation test_code_generator_generation: ./script/code_generator/check_git_change_code_generator.sh ./addons/TechnoLibre_odoo-code-generator-template - time ./script/db_restore.py --database code_generator + ./script/db_restore.py --database code_generator ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo ./addons/TechnoLibre_odoo-code-generator-template ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo_export_helpdesk ./addons/TechnoLibre_odoo-code-generator-template ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo_internal ./addons/TechnoLibre_odoo-code-generator-template @@ -216,20 +216,20 @@ test_code_generator_generation: .PHONY: test_code_generator_generation_extra test_code_generator_generation_extra: ./script/code_generator/check_git_change_code_generator.sh ./addons/OCA_server-tools/auto_backup - time ./script/db_restore.py --database code_generator + ./script/db_restore.py --database code_generator ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_auto_backup ./addons/OCA_server-tools/auto_backup .PHONY: test_code_generator_code_i18n test_code_generator_code_i18n: ./script/code_generator/check_git_change_code_generator.sh ./addons/TechnoLibre_odoo-code-generator-template - time ./script/db_restore.py --database template + ./script/db_restore.py --database template ./script/addons/install_addons_dev.sh template demo_portal ./script/code_generator/install_and_test_code_generator.sh template code_generator_template_demo_portal ./addons/TechnoLibre_odoo-code-generator-template .PHONY: test_code_generator_code_i18n_extra test_code_generator_code_i18n_extra: ./script/code_generator/check_git_change_code_generator.sh ./addons/OCA_server-tools/auto_backup - time ./script/db_restore.py --database template + ./script/db_restore.py --database template ./script/addons/install_addons_dev.sh template auto_backup ./script/code_generator/install_and_test_code_generator.sh template code_generator_template_demo_sysadmin_cron ./addons/TechnoLibre_odoo-code-generator-template # To support i18n in auto_backup From 23a3464119b224139a1a268320a2dbb86bda0b5a Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Tue, 29 Jun 2021 03:10:58 -0400 Subject: [PATCH 42/44] [UPD] makefile increase test speed --- Makefile | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index de5776c..530bf36 100644 --- a/Makefile +++ b/Makefile @@ -147,12 +147,12 @@ addons_install_code_generator_basic: db_restore_erplibre_base_db_code_generator ./script/addons/install_addons_dev.sh code_generator code_generator .PHONY: addons_install_code_generator_featured -addons_install_code_generator_featured: addons_install_code_generator_basic +addons_install_code_generator_featured: db_restore_erplibre_base_db_code_generator ./script/addons/install_addons_dev.sh code_generator code_generator_cron,code_generator_hook,code_generator_portal .PHONY: addons_install_code_generator_full -addons_install_code_generator_full: addons_install_code_generator_featured - ./script/addons/install_addons_dev.sh code_generator code_generator_db_servers,code_generator_website_snippet,code_generator_geoengine,code_generator_theme_website,code_generator_website_leaflet +addons_install_code_generator_full: db_restore_erplibre_base_db_code_generator + ./script/addons/install_addons_dev.sh code_generator code_generator_cron,code_generator_hook,code_generator_portal,code_generator_db_servers,code_generator_website_snippet,code_generator_geoengine,code_generator_theme_website,code_generator_website_leaflet .PHONY: addons_install_code_generator_demo addons_install_code_generator_demo: @@ -167,13 +167,14 @@ addons_reinstall_code_generator_demo: addons_uninstall_code_generator_demo addon .PHONY: addons_install_all_code_generator_demo addons_install_all_code_generator_demo: db_restore_erplibre_base_db_code_generator - ./script/addons/install_addons_dev.sh code_generator code_generator_demo - ./script/addons/install_addons_dev.sh code_generator code_generator_demo_export_helpdesk - ./script/addons/install_addons_dev.sh code_generator code_generator_demo_internal - ./script/addons/install_addons_dev.sh code_generator code_generator_demo_portal - ./script/addons/install_addons_dev.sh code_generator code_generator_demo_theme_website - ./script/addons/install_addons_dev.sh code_generator code_generator_demo_website_leaflet - ./script/addons/install_addons_dev.sh code_generator code_generator_demo_website_snippet + ./script/addons/install_addons_dev.sh code_generator code_generator_demo,code_generator_demo_export_helpdesk,code_generator_demo_internal,code_generator_demo_portal,code_generator_demo_theme_website,code_generator_demo_website_leaflet,code_generator_demo_website_snippet +# ./script/addons/install_addons_dev.sh code_generator code_generator_demo +# ./script/addons/install_addons_dev.sh code_generator code_generator_demo_export_helpdesk +# ./script/addons/install_addons_dev.sh code_generator code_generator_demo_internal +# ./script/addons/install_addons_dev.sh code_generator code_generator_demo_portal +# ./script/addons/install_addons_dev.sh code_generator code_generator_demo_theme_website +# ./script/addons/install_addons_dev.sh code_generator code_generator_demo_website_leaflet +# ./script/addons/install_addons_dev.sh code_generator code_generator_demo_website_snippet .PHONY: addons_install_all_code_generator_template addons_install_all_code_generator_template: @@ -205,13 +206,14 @@ test_format: test_code_generator_generation: ./script/code_generator/check_git_change_code_generator.sh ./addons/TechnoLibre_odoo-code-generator-template ./script/db_restore.py --database code_generator - ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo ./addons/TechnoLibre_odoo-code-generator-template - ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo_export_helpdesk ./addons/TechnoLibre_odoo-code-generator-template - ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo_internal ./addons/TechnoLibre_odoo-code-generator-template - ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo_portal ./addons/TechnoLibre_odoo-code-generator-template - ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo_theme_website ./addons/TechnoLibre_odoo-code-generator-template - ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo_website_leaflet ./addons/TechnoLibre_odoo-code-generator-template - ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo_website_snippet ./addons/TechnoLibre_odoo-code-generator-template + ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo,code_generator_demo_export_helpdesk,code_generator_demo_internal,code_generator_demo_portal,code_generator_demo_theme_website,code_generator_demo_website_leaflet,code_generator_demo_website_snippet ./addons/TechnoLibre_odoo-code-generator-template +# ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo ./addons/TechnoLibre_odoo-code-generator-template +# ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo_export_helpdesk ./addons/TechnoLibre_odoo-code-generator-template +# ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo_internal ./addons/TechnoLibre_odoo-code-generator-template +# ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo_portal ./addons/TechnoLibre_odoo-code-generator-template +# ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo_theme_website ./addons/TechnoLibre_odoo-code-generator-template +# ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo_website_leaflet ./addons/TechnoLibre_odoo-code-generator-template +# ./script/code_generator/install_and_test_code_generator.sh code_generator code_generator_demo_website_snippet ./addons/TechnoLibre_odoo-code-generator-template .PHONY: test_code_generator_generation_extra test_code_generator_generation_extra: From 44cf55d660319411d6de27f015e0f91838933597 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Sun, 27 Jun 2021 22:58:36 -0400 Subject: [PATCH 43/44] [ADD] code_generator documentation use case --- Makefile | 4 + doc/CODE_GENERATOR.base.md | 550 ++++++++++++++++++++++++++++++++++--- doc/CODE_GENERATOR.fr.md | 374 +++++++++++++++++++++++-- doc/CODE_GENERATOR.md | 217 ++++++++++++++- 4 files changed, 1082 insertions(+), 63 deletions(-) diff --git a/Makefile b/Makefile index 530bf36..44dcce4 100644 --- a/Makefile +++ b/Makefile @@ -111,6 +111,10 @@ db_drop_db_template: db_restore_erplibre_base_db_test: ./script/db_restore.py --database test +.PHONY: db_restore_erplibre_base_db_test_module_test +db_restore_erplibre_base_db_test_module_test: db_restore_erplibre_base_db_test + ./script/addons/install_addons.sh test test + .PHONY: db_restore_erplibre_base_db_test2 db_restore_erplibre_base_db_test2: ./script/db_restore.py --database test2 diff --git a/doc/CODE_GENERATOR.base.md b/doc/CODE_GENERATOR.base.md index 6d10a83..95ea584 100644 --- a/doc/CODE_GENERATOR.base.md +++ b/doc/CODE_GENERATOR.base.md @@ -12,7 +12,19 @@ Never run this on production environment, this create circular dependencies and will cause frustration to clean damage. -Ne jamais exécuter le générateur de code dans un environnement de production, il y a création de dépendance circulaire pouvant causer de la frustration à nettoyer tous les dommages. +Ne jamais exécuter le générateur de code dans un environnement de production, il y a création de dépendance circulaire pouvant causer de la frustration à nettoyer tous les dommages. D'ailleurs, il est nécessaire d'exécuter en mode développement, avec l'argument `--dev all`. + +L'objectif du générateur de code est de : +- utilisation du générateur via l'interface web; +- créer un nouveau module; +- modifier un module existant; +- exécuter les tests. + +Ce générateur de code, pour ERPLibre, a tout avantage d'être sous licence AGPLv3 et nécessite d'être dans une communauté active de logiciels libres puisqu'il sera plus efficace d'accéder à du code pour l'auto-apprentissage. Le libre permet : +- (Utiliser) L'utilisation de module sans restriction; +- (Copier) Copier des modules pour faciliter leur maintenance et leur pérennité; +- (Étudier) De comprendre le comportement des fonctionnalités; +- (Modifier) Modifier un module existant pour l'améliorer et pouvoir le redistribuer à la communauté; ``` @@ -29,9 +41,9 @@ Modules Il y a 3 types de module dans le contexte du générateur de code : -1. [A Template generates a Template or a Code_Generator.](#crer-votre-premier-code_generator) -2. Un Code_Generator génère un module. -3. Un Template lis un module pour générer un Code_Generator. +1. [A Template generates a Template or a Code_Generator.](#crer-votre-premier-code_generator), le chef d'orchestre qui permet de gérer plusieurs générateur de code. +2. Un Code_Generator génère un module, c'est un moule à module généré. +3. Un Template lit un module pour générer un Code_Generator. Warning, be careful to your code, always commit after a manipulation, because the mode enable_sync_code erase data, only the git will save you! @@ -39,28 +51,6 @@ Warning, be careful to your code, always commit after a manipulation, because th Attention pour ne pas écraser votre code, toujours commiter après une manipulation, l'utilisation du mode enable_sync_code peut effacer des données. Seul git vous sauvera! - -TODO -Il y a 4 objectifs sur le générateur : -+ utilisation du générateur via l'interface web -+ créer un nouveau module, -+ modifier un module existant -+ exécuter les tests. - -test : -- code generator -- code generator extra (externe au repo template) -- template -- création d'un nouveau module direct ou chaine complète - - tester chaque étape de la création -- i18n (définir les différents cas) - -Suggestion de réduire les config avec make config_ pour les tests. - -TODO expliquer les modules/fonctionnalités actuellements supportés. portail WIP, snippet website WIP, cron, web vue tree+form, geoengine WIP, theme website, hook, db_servers WIP, exportation de donnée en module -TODO expliquer objectif des 4 libertés -TODO rechanger les termes pour : orcherstre + moule + module - ## Manual generator with web interface @@ -105,6 +95,477 @@ Ouvrir le navigateur sur [http://localhost:8069](http://localhost:8069). Utilisa Ouvrir l'application `Code Generator` et créer un `Module`. Remplir les champs requis et générer avec `Action/Generate code`. + +### Create model-view module + + +### Créer un module modèle avec vue + + +```bash +make addons_install_code_generator_basic +make run_code_generator +``` + + +TODO + + +Pour des références techniques, voir module : +- code_generator_template_demo_portal +- code_generator_demo_portal +- code_generator_demo_internal +- demo_portal +- demo_internal + + +TODO + + +Aller dans le module «Code generator» et créer un module «test». +- Sur l'onglet «Information», activer «Enable Sync Code» +- Sur l'onglet «Technical Data», activer «Application». +- Sur l'onglet «Elements»/«Models», ajouter un modèle et sauvegarder. +- Appuyer sur le bouton «Views» + - Appuyer «Generate» + +Générer le module avec «Action/Générer code». + +Tester sur : + +```bash +make db_restore_erplibre_base_db_test_module_test +make run_test +``` + + +### Create portal module + + +### Créer un module avec la vue portail + + +```bash +make addons_install_code_generator_basic +./script/addons/install_addons.sh code_generator code_generator_portal +make run_code_generator +``` + + +TODO + + +Pour des références techniques, voir module : +- code_generator_template_demo_portal +- code_generator_demo_portal +- code_generator_demo_internal +- demo_portal +- demo_internal + + +TODO + + +Aller dans le module «Code generator» et créer un module «test». +- Sur l'onglet «Information», activer «Enable Sync Code» +- Sur l'onglet «Technical Data», activer «Application». +- Sur l'onglet «Elements»/«Models», ajouter un modèle et sauvegarder. +- Appuyer sur le bouton «Views» + - Désactiver «Enable all feature» + - Dans l'onglet «Portal» + - Activer «Enable portal feature» + - Appuyer «Generate» + +Générer le module avec «Action/Générer code». + +Tester sur : + +```bash +make db_restore_erplibre_base_db_test_module_test +make run_test +``` + + +TODO + + +Ajouter des données dans votre nouveau module «test». + +Aller sur le portail pour visualiser les données, à l'adresse `/my`. + + +### Create hook module for installation + + +### Créer un module crochet pour l'installation + + +TODO + + +Le crochet nommé «hook» permet d'exécuter du code en +- Pré-initialisation du module +- Post-initialisation du module +- Désinstallation du module + +Pour des références techniques, voir module : +- code_generator_demo + + +```bash +make addons_install_code_generator_basic +./script/addons/install_addons.sh code_generator code_generator_hook +make run_code_generator +``` + + +TODO + + +Aller dans le module «Code generator» et créer un module «test». +- Sur l'onglet «Information», activer «Enable Sync Code» +- Sur l'onglet «Hook» + - Activer «Show post_init_hook» + - Ajouter le code suivant dans la fenêtre qui est apparu : + + +```python +with api.Environment.manage(): + env = api.Environment(cr, SUPERUSER_ID, {}) + print("Hello World") +``` + + +TODO + + +Générer le module avec «Action/Générer code». + +Tester et chercher dans la console "Hello World" : + +```bash +make db_restore_erplibre_base_db_test_module_test +``` + + +### Create cron module + + +### Créer un module d'exécution de code sur une plage horaire + + +TODO + + +Permettre d'exécuter du code basé sur des séquences de temps ou des moments spécifiques à répétition. + +Pour des références techniques, voir module : +- code_generator_template_demo_sysadmin_cron +- code_generator_auto_backup +- auto_backup + + +```bash +make addons_install_code_generator_basic +./script/addons/install_addons.sh code_generator code_generator_cron +make run_code_generator +``` + + +TODO + + +Aller dans le module «Code generator» et créer un module «test». +- Sur l'onglet «Information», activer «Enable Sync Code» +- Sur l'onglet «Cron» + - Ajouter un cron + - Choisir le «Modèle» : «Contact» + - Choisir unité de temps en «Minutes» dans «Exécuter tous les» + - Modifier «Nombre d'appel» à -1 pour exécution sans arrêt. + - Activer «Force nextcall» pour permettre que l'interval soit basé sur le moment d'installation du module + - Ajouter le code : + + +```python +log("Coucou") +``` + + +TODO + + +Générer le module avec «Action/Générer code». + +Tester : + +```bash +make db_restore_erplibre_base_db_test_module_test +make run_test +``` + + +TODO + + +Avec les outils développeur, aller regarder les logs dans l'application «Configuration»/Technique/«Structure de base de donnée»/Historisation. Des informations dans le temps apparaîtront avec le mot «Coucou». + + +### Create website snippet module + + +### Créer un module de snippet pour le site web + + +In progress + + +En progression, non terminé + + +```bash +make addons_install_code_generator_basic +./script/addons/install_addons.sh code_generator code_generator_website_snippet +make run_code_generator +``` + + +TODO + + +Pour des références techniques, voir module : +- code_generator_template_demo_website_snippet +- code_generator_demo_website_snippet +- demo_website_snippet + +Puis dans le repo addons/ERPLibre_erplibre_theme_addons, branche code_generator_erplibre_website_snippets +- code_generator_erplibre_website_snippets + + +TODO + + +Aller dans le module «Code generator» et créer un module «test». +- Sur l'onglet «Information», activer «Enable Sync Code» + +TODO Incomplet + + +### Create geoengine with Leaflet module + + +### Créer un module de gestion de coordonnée géospatial avec Leaflet + + +```bash +make addons_install_code_generator_basic +./script/addons/install_addons.sh code_generator code_generator_website_leaflet +make run_code_generator +``` + + +TODO + + +Pour des références techniques, voir module : +- code_generator_demo_website_leaflet +- demo_website_leaflet + + +TODO + + +Aller dans le module «Code generator» et créer un module «test». +- Sur l'onglet «Information», activer «Enable Sync Code» +- Sur l'onglet «Technical Data» + - Activer «Application» + - Ajouter la dépendance du geo_engine «Geospatial support for System» +- Sur l'onglet «Elements»/«Models» + - Ajouter un modèle «test» + - Ajouter un champs de type «geo_». Le «geo_point» fonctionne bien. Si vous ajoutez plusieurs géométrie, tel que «geo_point», «geo_line» et «geo_polygon», il faut ajouter le champs «type» avec les valeurs du nom des champs choisis en option de sélection, exemple `[('geo_point', 'Geo Point'),('geo_polygon', 'Geo Polygon')]` + - Ajouter le champs optionnel «html_text» de type «html» pour pouvoir afficher du texte dessus. +- Appuyer sur le bouton «Controllers» + - Ajouter le modèle du module actuel, «test» + - Appuyer «Generate» +- Appuyer sur le bouton «Views» + - Désactiver «Enable all feature» + - Dans l'onglet «Website» + - Activer «Enable website leaflet feature» + - Activer «Enable geoengine feature» + - Appuyer «Generate» + +Générer le module avec «Action/Générer code». + +Tester sur : + +```bash +make db_restore_erplibre_base_db_test_module_test +make run_test +``` + + +TODO + + +Ajouter les permissions d'utilisation, dans l'application «Configuration», «Gérer les droits d'accès». Sur votre utilisateur, ajouter «Geoengine Admin». + +Aller sur l'application «test», créer un «geo_point». + +Aller sur la page du site web, ajouter le snippet «Leaflet». Chercher le point qui a été ajouté sur la carte du monde. + + +### Create theme module for website + + +### Créer un module thème pour site web + + +TODO + + +Pour des références techniques, voir module : +- code_generator_demo_theme_website + + +```bash +make addons_install_code_generator_basic +./script/addons/install_addons.sh code_generator code_generator_theme_website +make run_code_generator +``` + +TODO + + +Aller dans le module «Code generator» et créer un module «test». +- Sur l'onglet «Information», activer «Enable Sync Code» +- Sur l'onglet «Technical Data», activer «Website theme». +- Appuyer sur le bouton «Views» + - Aller à l'onglet «theme_website» + - Mettre les couleurs désirés + - Appuyer «Generate» + +Générer le module avec «Action/Générer code». + +Ce module doit être installé manuellement pour l'instant. + + +```bash +make db_restore_erplibre_base_db_test +./script/addons/install_addons.sh test website +make run_test +``` + + +TODO + + +Aller dans l'interface web, Application «Configuration», «Paramètres Généraux»/«Site Web»/«Choisissez un thème». Installer le thème «TEST». Puis aller la page du site web, les couleurs sont dans «Personnaliser»/«Personnaliser le thème». + + +### Extract data to module + + +### Extraire les données vers un module + + +TODO + + +L'exemple est avec le helpdesk. Installer le module helpdesk_mgmt : + +Pour des références techniques, voir module : +- code_generator_demo_export_helpdesk +- code_generator_demo_export_website +- demo_website_data +- demo_helpdesk_data + + +```bash +make addons_install_code_generator_basic +./script/addons/install_addons.sh code_generator helpdesk_mgmt +make run_code_generator +``` + +TODO + + +Créer un ticket dans l'application «Helpdesk» dans l'interface web. + +Aller dans le module «Code generator» et créer un module «test». +- Sur l'onglet «Information», activer «Enable Sync Code» +- Sur l'onglet «Technical Data», activer «Only export data». +- Appuyer sur le bouton «Models» + - Choisissez dans «Models» : + - «helpdesk.ticket» + - Activer «Clear field blacklisted» + - Enlever les éléments suivant de «Fields» : + - name + - description + - number + - Appuyer «Generate» + +Générer le module avec «Action/Générer code». + +```bash +make db_restore_erplibre_base_db_test_module_test +``` + + +### Migrate external database into module of migration + + +### Migrer une base de donnée externe en module de migration + + +TODO + + +En progression. + +Pour des références techniques, voir module : +- ?? + + +```bash +make addons_install_code_generator_basic +./script/addons/install_addons.sh code_generator code_generator_db_servers +make run_code_generator +``` + +TODO + + +Aller dans le module «Code generator», menu «Databases»/«Databases» et créer un connecteur vers une base de donnée. + +À compléter... + + +### Migrate from website to model with PDF data + + +### Migrer d'un site web vers un modèle de donnée avec des données format PDF + + +TODO + + +En progression, ce n'est pas encore supporté via l'interface web. + +Cette technique permet d'aller lire du Javascript sur un site web pour lire ensuite le HTML, c'est à dire la vue, et en comprendre l'information pour créer un modèle. + +Pour des références techniques, voir module : +- code_generator_demo_converter_js +- business_plan_import_pdf + +Attention, il faut mettre à jour les variables, dans les fichiers hook.py qui permettront d'extraire des données sur le site web à copier. Aucun exemple public n'est accessible pour le moment. + + +```bash +make db_restore_erplibre_base_db_code_generator +./script/addons/install_addons_dev.sh code_generator code_generator_demo_converter_js +make db_restore_erplibre_base_db_test +./script/addons/install_addons_dev.sh test business_plan_import_pdf +``` + ## Prepare a DB @@ -123,18 +584,25 @@ make db_restore_erplibre_base_db_code_generator ``` -## Test code generator +TODO -## Tester le générateur de code +Pour de meilleur performance d'exécution, réduire la quantité de «repo addons» permet d'accélérer l'installation, exécuter : + + +```bash +make config_gen_code_generator +``` TODO -Tester la génération des modules internes du générateur, créant les démos à partir de leur générateur respectif. +Pour revenir à la configuration normal, en production, exécuter : + + ```bash -make test_code_generator_generation +make config_gen_all ``` @@ -207,7 +675,7 @@ make addons_install_code_generator_demo Name your module begin with `MODULE_NAME = "code_generator_"` -Nommé votre module qui débute par `MODULE_NAME = "code_generator_"` +Au besoin, renommé votre module qui débute par `MODULE_NAME = "code_generator_"` Continue the example, you generated the template `code_generator_template_demo_website_snippet`, this will overwrite `code_generator_demo_website_snippet`: @@ -293,6 +761,7 @@ Générer votre module : ```bash +make db_restore_erplibre_base_db_code_generator ./script/addons/install_addons_dev.sh code_generator code_generator_demo_website_snippet ``` @@ -306,7 +775,7 @@ Maintenant, vous pouvez le tester! Pour info, on ne peut pas installer un module -Il est maintenant possible de modifier les paramètres via l'interface manuelle pour ce module, puis le regénérer en effaçant la BD. Ajouter un modèle. +Il est maintenant possible de modifier les paramètres via l'interface manuelle pour ce module, puis le regénérer en effaçant la BD. Ajouter un modèle et une vue. ```bash @@ -319,19 +788,25 @@ make db_restore_erplibre_base_db_code_generator Faire la boucle d'amélioration, commiter le code pour avoir une traçabilité des changements. -Ensuite, modifier la valeur `enable_sync_template` à `True` dans le fichier template, de l'exemple `code_generator_template_demo_website_snippet`. +Ensuite, modifier la valeur `enable_sync_template` à `True`, `enable_template_wizard_view` à `True`, `template_model_name` avec un modèle existant, dans le fichier template, de l'exemple `code_generator_template_demo_website_snippet`. ```python value["enable_sync_template"] = True +value["enable_template_wizard_view"] = True +value["template_model_name"] = "test;test2" ``` +TODO Exécuter l'installation du template pour qu'il se synchronise sur le module généré. + + ```bash make db_restore_erplibre_base_db_template +./script/addons/install_addons_dev.sh template demo_website_snippet ./script/addons/install_addons_dev.sh template code_generator_template_demo_website_snippet ``` @@ -419,6 +894,15 @@ TODO Une bonne manière de tester un générateur de code est de valider qu'il génère le même code, il ne devient pas nécessaire de tester les fonctionnalités, puisque le comportement est la génération. + +```bash +make test +``` + + +TODO + + Tester les générations simples : diff --git a/doc/CODE_GENERATOR.fr.md b/doc/CODE_GENERATOR.fr.md index 695d82d..c7d9a03 100644 --- a/doc/CODE_GENERATOR.fr.md +++ b/doc/CODE_GENERATOR.fr.md @@ -1,6 +1,18 @@ # Comment générer du code -Ne jamais exécuter le générateur de code dans un environnement de production, il y a création de dépendance circulaire pouvant causer de la frustration à nettoyer tous les dommages. +Ne jamais exécuter le générateur de code dans un environnement de production, il y a création de dépendance circulaire pouvant causer de la frustration à nettoyer tous les dommages. D'ailleurs, il est nécessaire d'exécuter en mode développement, avec l'argument `--dev all`. + +L'objectif du générateur de code est de : +- utilisation du générateur via l'interface web; +- créer un nouveau module; +- modifier un module existant; +- exécuter les tests. + +Ce générateur de code, pour ERPLibre, a tout avantage d'être sous licence AGPLv3 et nécessite d'être dans une communauté active de logiciels libres puisqu'il sera plus efficace d'accéder à du code pour l'auto-apprentissage. Le libre permet : +- (Utiliser) L'utilisation de module sans restriction; +- (Copier) Copier des modules pour faciliter leur maintenance et leur pérennité; +- (Étudier) De comprendre le comportement des fonctionnalités; +- (Modifier) Modifier un module existant pour l'améliorer et pouvoir le redistribuer à la communauté; ``` Modules @@ -10,9 +22,9 @@ Modules ``` Il y a 3 types de module dans le contexte du générateur de code : -1. [A Template generates a Template or a Code_Generator.](#crer-votre-premier-code_generator) -2. Un Code_Generator génère un module. -3. Un Template lis un module pour générer un Code_Generator. +1. [A Template generates a Template or a Code_Generator.](#crer-votre-premier-code_generator), le chef d'orchestre qui permet de gérer plusieurs générateur de code. +2. Un Code_Generator génère un module, c'est un moule à module généré. +3. Un Template lit un module pour générer un Code_Generator. Attention pour ne pas écraser votre code, toujours commiter après une manipulation, l'utilisation du mode enable_sync_code peut effacer des données. Seul git vous sauvera! @@ -44,6 +56,314 @@ Ouvrir le navigateur sur [http://localhost:8069](http://localhost:8069). Utilisa Ouvrir l'application `Code Generator` et créer un `Module`. Remplir les champs requis et générer avec `Action/Generate code`. +### Créer un module modèle avec vue + +```bash +make addons_install_code_generator_basic +make run_code_generator +``` + +Pour des références techniques, voir module : +- code_generator_template_demo_portal +- code_generator_demo_portal +- code_generator_demo_internal +- demo_portal +- demo_internal + +Aller dans le module «Code generator» et créer un module «test». +- Sur l'onglet «Information», activer «Enable Sync Code» +- Sur l'onglet «Technical Data», activer «Application». +- Sur l'onglet «Elements»/«Models», ajouter un modèle et sauvegarder. +- Appuyer sur le bouton «Views» + - Appuyer «Generate» + +Générer le module avec «Action/Générer code». + +Tester sur : +```bash +make db_restore_erplibre_base_db_test_module_test +make run_test +``` + +### Créer un module avec la vue portail + +```bash +make addons_install_code_generator_basic +./script/addons/install_addons.sh code_generator code_generator_portal +make run_code_generator +``` + +Pour des références techniques, voir module : +- code_generator_template_demo_portal +- code_generator_demo_portal +- code_generator_demo_internal +- demo_portal +- demo_internal + +Aller dans le module «Code generator» et créer un module «test». +- Sur l'onglet «Information», activer «Enable Sync Code» +- Sur l'onglet «Technical Data», activer «Application». +- Sur l'onglet «Elements»/«Models», ajouter un modèle et sauvegarder. +- Appuyer sur le bouton «Views» + - Désactiver «Enable all feature» + - Dans l'onglet «Portal» + - Activer «Enable portal feature» + - Appuyer «Generate» + +Générer le module avec «Action/Générer code». + +Tester sur : +```bash +make db_restore_erplibre_base_db_test_module_test +make run_test +``` + +Ajouter des données dans votre nouveau module «test». + +Aller sur le portail pour visualiser les données, à l'adresse `/my`. + +### Créer un module crochet pour l'installation + +Le crochet nommé «hook» permet d'exécuter du code en +- Pré-initialisation du module +- Post-initialisation du module +- Désinstallation du module + +Pour des références techniques, voir module : +- code_generator_demo + +```bash +make addons_install_code_generator_basic +./script/addons/install_addons.sh code_generator code_generator_hook +make run_code_generator +``` + +Aller dans le module «Code generator» et créer un module «test». +- Sur l'onglet «Information», activer «Enable Sync Code» +- Sur l'onglet «Hook» + - Activer «Show post_init_hook» + - Ajouter le code suivant dans la fenêtre qui est apparu : + +```python +with api.Environment.manage(): + env = api.Environment(cr, SUPERUSER_ID, {}) + print("Hello World") +``` + +Générer le module avec «Action/Générer code». + +Tester et chercher dans la console "Hello World" : +```bash +make db_restore_erplibre_base_db_test_module_test +``` + +### Créer un module d'exécution de code sur une plage horaire + +Permettre d'exécuter du code basé sur des séquences de temps ou des moments spécifiques à répétition. + +Pour des références techniques, voir module : +- code_generator_template_demo_sysadmin_cron +- code_generator_auto_backup +- auto_backup + +```bash +make addons_install_code_generator_basic +./script/addons/install_addons.sh code_generator code_generator_cron +make run_code_generator +``` + +Aller dans le module «Code generator» et créer un module «test». +- Sur l'onglet «Information», activer «Enable Sync Code» +- Sur l'onglet «Cron» + - Ajouter un cron + - Choisir le «Modèle» : «Contact» + - Choisir unité de temps en «Minutes» dans «Exécuter tous les» + - Modifier «Nombre d'appel» à -1 pour exécution sans arrêt. + - Activer «Force nextcall» pour permettre que l'interval soit basé sur le moment d'installation du module + - Ajouter le code : + +```python +log("Coucou") +``` + +Générer le module avec «Action/Générer code». + +Tester : +```bash +make db_restore_erplibre_base_db_test_module_test +make run_test +``` + +Avec les outils développeur, aller regarder les logs dans l'application «Configuration»/Technique/«Structure de base de donnée»/Historisation. Des informations dans le temps apparaîtront avec le mot «Coucou». + +### Créer un module de snippet pour le site web + +En progression, non terminé + +```bash +make addons_install_code_generator_basic +./script/addons/install_addons.sh code_generator code_generator_website_snippet +make run_code_generator +``` + +Pour des références techniques, voir module : +- code_generator_template_demo_website_snippet +- code_generator_demo_website_snippet +- demo_website_snippet + +Puis dans le repo addons/ERPLibre_erplibre_theme_addons, branche code_generator_erplibre_website_snippets +- code_generator_erplibre_website_snippets + +Aller dans le module «Code generator» et créer un module «test». +- Sur l'onglet «Information», activer «Enable Sync Code» + +TODO Incomplet + +### Créer un module de gestion de coordonnée géospatial avec Leaflet + +```bash +make addons_install_code_generator_basic +./script/addons/install_addons.sh code_generator code_generator_website_leaflet +make run_code_generator +``` + +Pour des références techniques, voir module : +- code_generator_demo_website_leaflet +- demo_website_leaflet + +Aller dans le module «Code generator» et créer un module «test». +- Sur l'onglet «Information», activer «Enable Sync Code» +- Sur l'onglet «Technical Data» + - Activer «Application» + - Ajouter la dépendance du geo_engine «Geospatial support for System» +- Sur l'onglet «Elements»/«Models» + - Ajouter un modèle «test» + - Ajouter un champs de type «geo_». Le «geo_point» fonctionne bien. Si vous ajoutez plusieurs géométrie, tel que «geo_point», «geo_line» et «geo_polygon», il faut ajouter le champs «type» avec les valeurs du nom des champs choisis en option de sélection, exemple `[('geo_point', 'Geo Point'),('geo_polygon', 'Geo Polygon')]` + - Ajouter le champs optionnel «html_text» de type «html» pour pouvoir afficher du texte dessus. +- Appuyer sur le bouton «Controllers» + - Ajouter le modèle du module actuel, «test» + - Appuyer «Generate» +- Appuyer sur le bouton «Views» + - Désactiver «Enable all feature» + - Dans l'onglet «Website» + - Activer «Enable website leaflet feature» + - Activer «Enable geoengine feature» + - Appuyer «Generate» + +Générer le module avec «Action/Générer code». + +Tester sur : +```bash +make db_restore_erplibre_base_db_test_module_test +make run_test +``` + +Ajouter les permissions d'utilisation, dans l'application «Configuration», «Gérer les droits d'accès». Sur votre utilisateur, ajouter «Geoengine Admin». + +Aller sur l'application «test», créer un «geo_point». + +Aller sur la page du site web, ajouter le snippet «Leaflet». Chercher le point qui a été ajouté sur la carte du monde. + +### Créer un module thème pour site web + +Pour des références techniques, voir module : +- code_generator_demo_theme_website + +```bash +make addons_install_code_generator_basic +./script/addons/install_addons.sh code_generator code_generator_theme_website +make run_code_generator +``` +Aller dans le module «Code generator» et créer un module «test». +- Sur l'onglet «Information», activer «Enable Sync Code» +- Sur l'onglet «Technical Data», activer «Website theme». +- Appuyer sur le bouton «Views» + - Aller à l'onglet «theme_website» + - Mettre les couleurs désirés + - Appuyer «Generate» + +Générer le module avec «Action/Générer code». + +Ce module doit être installé manuellement pour l'instant. + +```bash +make db_restore_erplibre_base_db_test +./script/addons/install_addons.sh test website +make run_test +``` + +Aller dans l'interface web, Application «Configuration», «Paramètres Généraux»/«Site Web»/«Choisissez un thème». Installer le thème «TEST». Puis aller la page du site web, les couleurs sont dans «Personnaliser»/«Personnaliser le thème». + +### Extraire les données vers un module + +L'exemple est avec le helpdesk. Installer le module helpdesk_mgmt : + +Pour des références techniques, voir module : +- code_generator_demo_export_helpdesk +- code_generator_demo_export_website +- demo_website_data +- demo_helpdesk_data + +```bash +make addons_install_code_generator_basic +./script/addons/install_addons.sh code_generator helpdesk_mgmt +make run_code_generator +``` +Créer un ticket dans l'application «Helpdesk» dans l'interface web. + +Aller dans le module «Code generator» et créer un module «test». +- Sur l'onglet «Information», activer «Enable Sync Code» +- Sur l'onglet «Technical Data», activer «Only export data». +- Appuyer sur le bouton «Models» + - Choisissez dans «Models» : + - «helpdesk.ticket» + - Activer «Clear field blacklisted» + - Enlever les éléments suivant de «Fields» : + - name + - description + - number + - Appuyer «Generate» + +Générer le module avec «Action/Générer code». +```bash +make db_restore_erplibre_base_db_test_module_test +``` + +### Migrer une base de donnée externe en module de migration + +En progression. + +Pour des références techniques, voir module : +- ?? + +```bash +make addons_install_code_generator_basic +./script/addons/install_addons.sh code_generator code_generator_db_servers +make run_code_generator +``` +Aller dans le module «Code generator», menu «Databases»/«Databases» et créer un connecteur vers une base de donnée. + +À compléter... + +### Migrer d'un site web vers un modèle de donnée avec des données format PDF + +En progression, ce n'est pas encore supporté via l'interface web. + +Cette technique permet d'aller lire du Javascript sur un site web pour lire ensuite le HTML, c'est à dire la vue, et en comprendre l'information pour créer un modèle. + +Pour des références techniques, voir module : +- code_generator_demo_converter_js +- business_plan_import_pdf + +Attention, il faut mettre à jour les variables, dans les fichiers hook.py qui permettront d'extraire des données sur le site web à copier. Aucun exemple public n'est accessible pour le moment. + +```bash +make db_restore_erplibre_base_db_code_generator +./script/addons/install_addons_dev.sh code_generator code_generator_demo_converter_js +make db_restore_erplibre_base_db_test +./script/addons/install_addons_dev.sh test business_plan_import_pdf +``` + ## Préparer une BD Ceci va détruire et créer une base de donnée nommé `code_generator`. @@ -52,11 +372,16 @@ Ceci va détruire et créer une base de donnée nommé `code_generator`. make db_restore_erplibre_base_db_code_generator ``` -## Tester le générateur de code +Pour de meilleur performance d'exécution, réduire la quantité de «repo addons» permet d'accélérer l'installation, exécuter : -Tester la génération des modules internes du générateur, créant les démos à partir de leur générateur respectif. ```bash -make test_code_generator_generation +make config_gen_code_generator +``` + +Pour revenir à la configuration normal, en production, exécuter : + +```bash +make config_gen_all ``` ## Créer votre premier `Code_Generator` @@ -91,13 +416,13 @@ make addons_install_code_generator_demo ### Générer un Code_Generator (suite de template) -Nommé votre module qui débute par `MODULE_NAME = "code_generator_"` +Au besoin, renommé votre module qui débute par `MODULE_NAME = "code_generator_"` Pour continuer avec l'exemple, généré le template `code_generator_template_demo_website_snippet`, ceci va écraser `code_generator_demo_website_snippet`: ```bash make db_restore_erplibre_base_db_template -./script/addons/install_addons.sh template code_generator_template_demo_website_snippet +./script/addons/install_addons_dev.sh template code_generator_template_demo_website_snippet ``` Aller à la section [Créer votre premier module](#crer-votre-premier-module) @@ -115,7 +440,7 @@ value["enable_template_code_generator_demo"] = False Pour continuer avec l'exemple, généré le template `code_generator_template_demo_website_snippet`, ceci va écraser `code_generator_demo_website_snippet`: ```bash -./script/addons/install_addons.sh code_generator code_generator_template_demo_website_snippet +./script/addons/install_addons_dev.sh code_generator code_generator_template_demo_website_snippet ``` ## Créer votre premier module @@ -135,30 +460,35 @@ lst_depend = [ Générer votre module : ```bash -./script/addons/install_addons.sh code_generator code_generator_demo_website_snippet +make db_restore_erplibre_base_db_code_generator +./script/addons/install_addons_dev.sh code_generator code_generator_demo_website_snippet ``` Maintenant, vous pouvez le tester! Pour info, on ne peut pas installer un module généré avec son générateur de code associé, puisqu'il y a une duplication des modèles! -Il est maintenant possible de modifier les paramètres via l'interface manuelle pour ce module, puis le regénérer en effaçant la BD. Ajouter un modèle. +Il est maintenant possible de modifier les paramètres via l'interface manuelle pour ce module, puis le regénérer en effaçant la BD. Ajouter un modèle et une vue. ```bash make db_restore_erplibre_base_db_code_generator -./script/addons/install_addons.sh code_generator code_generator_demo_website_snippet +./script/addons/install_addons_dev.sh code_generator code_generator_demo_website_snippet ``` Faire la boucle d'amélioration, commiter le code pour avoir une traçabilité des changements. -Ensuite, modifier la valeur `enable_sync_template` à `True` dans le fichier template, de l'exemple `code_generator_template_demo_website_snippet`. +Ensuite, modifier la valeur `enable_sync_template` à `True`, `enable_template_wizard_view` à `True`, `template_model_name` avec un modèle existant, dans le fichier template, de l'exemple `code_generator_template_demo_website_snippet`. ```python value["enable_sync_template"] = True +value["enable_template_wizard_view"] = True +value["template_model_name"] = "test;test2" ``` Exécuter l'installation du template pour qu'il se synchronise sur le module généré. + ```bash make db_restore_erplibre_base_db_template -./script/addons/install_addons.sh template code_generator_template_demo_website_snippet +./script/addons/install_addons_dev.sh template demo_website_snippet +./script/addons/install_addons_dev.sh template code_generator_template_demo_website_snippet ``` Prêt à tester, générer le module : @@ -166,7 +496,7 @@ Prêt à tester, générer le module : ```bash # Optional, reset test database make db_restore_erplibre_base_db_test -./script/addons/install_addons.sh test demo_website_snippet +./script/addons/install_addons_dev.sh test demo_website_snippet ``` # Comment générer les traductions i18n @@ -182,8 +512,8 @@ Premièrement, installer le module, par exemple `demo_portal`, et ensuite le tem ```bash make db_restore_erplibre_base_db_code_generator -./script/addons/install_addons.sh test demo_portal -./script/addons/install_addons.sh test code_generator_template_demo_portal +./script/addons/install_addons_dev.sh test demo_portal +./script/addons/install_addons_dev.sh test code_generator_template_demo_portal ``` # Synchroniser les champs du `Code_Generator` du module @@ -196,14 +526,18 @@ Exemple : ```bash make db_restore_erplibre_base_db_code_generator -./script/addons/install_addons.sh test demo_portal -./script/addons/install_addons.sh test code_generator_template_demo_portal +./script/addons/install_addons_dev.sh test demo_portal +./script/addons/install_addons_dev.sh test code_generator_template_demo_portal ``` # Tester le générateur de code Une bonne manière de tester un générateur de code est de valider qu'il génère le même code, il ne devient pas nécessaire de tester les fonctionnalités, puisque le comportement est la génération. +```bash +make test +``` + Tester les générations simples : ```bash diff --git a/doc/CODE_GENERATOR.md b/doc/CODE_GENERATOR.md index f6c22c7..6f5dc4c 100644 --- a/doc/CODE_GENERATOR.md +++ b/doc/CODE_GENERATOR.md @@ -38,6 +38,179 @@ Ouvrir le navigateur sur [http://localhost:8069](http://localhost:8069). Utilisa Ouvrir l'application `Code Generator` et créer un `Module`. Remplir les champs requis et générer avec `Action/Generate code`. +### Create model-view module + +```bash +make addons_install_code_generator_basic +make run_code_generator +``` + +TODO + +TODO + +```bash +make db_restore_erplibre_base_db_test_module_test +make run_test +``` + +### Create portal module + +```bash +make addons_install_code_generator_basic +./script/addons/install_addons.sh code_generator code_generator_portal +make run_code_generator +``` + +TODO + +TODO + +```bash +make db_restore_erplibre_base_db_test_module_test +make run_test +``` + +TODO + +### Create hook module for installation + +TODO + +```bash +make addons_install_code_generator_basic +./script/addons/install_addons.sh code_generator code_generator_hook +make run_code_generator +``` + +TODO + +```python +with api.Environment.manage(): + env = api.Environment(cr, SUPERUSER_ID, {}) + print("Hello World") +``` + +TODO + +```bash +make db_restore_erplibre_base_db_test_module_test +``` + +### Create cron module + +TODO + +```bash +make addons_install_code_generator_basic +./script/addons/install_addons.sh code_generator code_generator_cron +make run_code_generator +``` + +TODO + +```python +log("Coucou") +``` + +TODO + +```bash +make db_restore_erplibre_base_db_test_module_test +make run_test +``` + +TODO + +### Create website snippet module + +In progress + +```bash +make addons_install_code_generator_basic +./script/addons/install_addons.sh code_generator code_generator_website_snippet +make run_code_generator +``` + +TODO + +TODO + +### Create geoengine with Leaflet module + +```bash +make addons_install_code_generator_basic +./script/addons/install_addons.sh code_generator code_generator_website_leaflet +make run_code_generator +``` + +TODO + +TODO + +```bash +make db_restore_erplibre_base_db_test_module_test +make run_test +``` + +TODO + +### Create theme module for website + +TODO + +```bash +make addons_install_code_generator_basic +./script/addons/install_addons.sh code_generator code_generator_theme_website +make run_code_generator +``` +TODO + +```bash +make db_restore_erplibre_base_db_test +./script/addons/install_addons.sh test website +make run_test +``` + +TODO + +### Extract data to module + +TODO + +```bash +make addons_install_code_generator_basic +./script/addons/install_addons.sh code_generator helpdesk_mgmt +make run_code_generator +``` +TODO + +```bash +make db_restore_erplibre_base_db_test_module_test +``` + +### Migrate external database into module of migration + +TODO + +```bash +make addons_install_code_generator_basic +./script/addons/install_addons.sh code_generator code_generator_db_servers +make run_code_generator +``` +TODO + +### Migrate from website to model with PDF data + +TODO + +```bash +make db_restore_erplibre_base_db_code_generator +./script/addons/install_addons_dev.sh code_generator code_generator_demo_converter_js +make db_restore_erplibre_base_db_test +./script/addons/install_addons_dev.sh test business_plan_import_pdf +``` + ## Prepare a DB This will destroy and create database named `code_generator`. @@ -46,10 +219,18 @@ This will destroy and create database named `code_generator`. make db_restore_erplibre_base_db_code_generator ``` -## Test code generator +TODO + +```bash +make config_gen_code_generator +``` TODO +```bash +make config_gen_all +``` + ## Create your first `Code_Generator` Edit [Code Generator Demo](./../addons/TechnoLibre_odoo-code-generator/code_generator_demo/hooks.py) and update `# TODO HUMAN:` @@ -90,7 +271,7 @@ Continue the example, you generated the template `code_generator_template_demo_w ```bash make db_restore_erplibre_base_db_template -./script/addons/install_addons.sh template code_generator_template_demo_website_snippet +./script/addons/install_addons_dev.sh template code_generator_template_demo_website_snippet ``` Go to section [Create your first module](#create-your-first-module) @@ -108,7 +289,7 @@ value["enable_template_code_generator_demo"] = False Continue the example, you generated the template `code_generator_template_demo_website_snippet`, this will overwrite `code_generator_demo_website_snippet`: ```bash -./script/addons/install_addons.sh code_generator code_generator_template_demo_website_snippet +./script/addons/install_addons_dev.sh code_generator code_generator_template_demo_website_snippet ``` ## Create your first Module @@ -128,7 +309,8 @@ lst_depend = [ Generate your module: ```bash -./script/addons/install_addons.sh code_generator code_generator_demo_website_snippet +make db_restore_erplibre_base_db_code_generator +./script/addons/install_addons_dev.sh code_generator code_generator_demo_website_snippet ``` Now, you can test it! Note, you cannot install a generated module with is code_generator associated, because duplicated @@ -137,21 +319,30 @@ models! ```bash make db_restore_erplibre_base_db_code_generator -./script/addons/install_addons.sh code_generator code_generator_demo_website_snippet +./script/addons/install_addons_dev.sh code_generator code_generator_demo_website_snippet ``` ```python value["enable_sync_template"] = True +value["enable_template_wizard_view"] = True +value["template_model_name"] = "test;test2" ``` +TODO + +```bash +make db_restore_erplibre_base_db_template +./script/addons/install_addons_dev.sh template demo_website_snippet +./script/addons/install_addons_dev.sh template code_generator_template_demo_website_snippet +``` Ready to test, generate your module: ```bash # Optional, reset test database make db_restore_erplibre_base_db_test -./script/addons/install_addons.sh test demo_website_snippet +./script/addons/install_addons_dev.sh test demo_website_snippet ``` # How to generate i18n translation @@ -167,8 +358,8 @@ First, install the module, example `demo_portal`, and after the template, exampl ```bash make db_restore_erplibre_base_db_code_generator -./script/addons/install_addons.sh test demo_portal -./script/addons/install_addons.sh test code_generator_template_demo_portal +./script/addons/install_addons_dev.sh test demo_portal +./script/addons/install_addons_dev.sh test code_generator_template_demo_portal ``` # Sync Code_Generator fields from Module @@ -182,14 +373,20 @@ Example: ```bash make db_restore_erplibre_base_db_code_generator -./script/addons/install_addons.sh test demo_portal -./script/addons/install_addons.sh test code_generator_template_demo_portal +./script/addons/install_addons_dev.sh test demo_portal +./script/addons/install_addons_dev.sh test code_generator_template_demo_portal ``` # Test the code generator TODO +```bash +make test +``` + +TODO + ```bash make test_code_generator_generation ``` From 8dc552f82b0f479ae048abc848302a945d414370 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Wed, 30 Jun 2021 19:44:11 -0400 Subject: [PATCH 44/44] [UPD] changelog from v1.1.1 --- CHANGELOG.md | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22b480c..50fd137 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,14 +9,42 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Added +- Adapt script to give an execution status +- Multilingual markdown +- Guide to use Cloudflare with DDNS +- Script to check git diff and ignore date +- Repo with ERPLibre image +- Improve git repo usage, filter repo by use case + +#### Makefile +- Format code +- Code generator test +- Addons installation +- OS installation +- Restore database +- Docker execution + +#### Code generator - Code generator for Odoo module, depending of ERPLibre - Support map geoengine -- Multilingual markdown +- Support i18n +- Script to transform Python and XML to Python code writer script to regenerate themselves ### Changed -- Downgrade postgresql to 11 to support postgis -- Travis CI +- Update Python dependency with Poetry +- Format all Python code with black + +#### Docker + +- Use buster python 3.7.7 image to remove pyenv +- Update Postgresql to support Postgis +- Support volume addons /ERPLibre/addons/addons + +### Fixed + +- Ubuntu installation +- Poetry installation ## [1.1.1] - 2020-12-11