Merge branch 'develop'
- Support private file - Update odoo 14 and 16 - selenium lib support opening kdbx
This commit is contained in:
commit
63970ed2f5
12 changed files with 120 additions and 12 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -43,4 +43,3 @@ requirements.txt
|
|||
requirement/ignore_requirements.txt
|
||||
screenshots
|
||||
screencasts
|
||||
script/todo/todo_override.json
|
||||
|
|
|
|||
|
|
@ -53,14 +53,26 @@ docker_exec_erplibre_repo_show_status:
|
|||
docker_build_odoo_16:
|
||||
./script/docker/docker_build.sh --odoo_16
|
||||
|
||||
.PHONY: docker_build_odoo_16_clean
|
||||
docker_build_odoo_16_clean:
|
||||
./script/docker/docker_build.sh --odoo_16 --no-cache
|
||||
|
||||
.PHONY: docker_build_odoo_14
|
||||
docker_build_odoo_14:
|
||||
./script/docker/docker_build.sh --odoo_14
|
||||
|
||||
.PHONY: docker_build_odoo_14_clean
|
||||
docker_build_odoo_14_clean:
|
||||
./script/docker/docker_build.sh --odoo_14 --no-cache
|
||||
|
||||
.PHONY: docker_build_odoo_12
|
||||
docker_build_odoo_12:
|
||||
./script/docker/docker_build.sh --odoo_12
|
||||
|
||||
.PHONY: docker_build_odoo_12_clean
|
||||
docker_build_odoo_12_clean:
|
||||
./script/docker/docker_build.sh --odoo_12 --no-cache
|
||||
|
||||
# build docker release
|
||||
.PHONY: docker_build_release
|
||||
docker_build_release:
|
||||
|
|
|
|||
|
|
@ -221,3 +221,9 @@ cat /proc/sys/fs/inotify/max_user_watches
|
|||
|
||||
Tips, when doing `sudo sysctl -p --system`, validate the order of the process, another process can overwrite your new
|
||||
value.
|
||||
|
||||
## How killing all process from selenium
|
||||
|
||||
```bash
|
||||
pkill -f "firefox.*--marionette"
|
||||
```
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ services:
|
|||
# See the volume section at the end of the file
|
||||
- erplibre_data_dir:/home/odoo/.local/share/Odoo
|
||||
- ./addons/addons:/ERPLibre/addons/addons
|
||||
- ./private:/ERPLibre/private
|
||||
- erplibre_conf:/etc/odoo
|
||||
restart: always
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
version: "3.3"
|
||||
services:
|
||||
ERPLibre:
|
||||
image: technolibre/erplibre:1.6.0_odoo_14.0_2a8af84
|
||||
image: technolibre/erplibre:1.6.0_odoo_14.0_1890768
|
||||
ports:
|
||||
- 8069:8069
|
||||
- 8071:8071
|
||||
|
|
@ -27,6 +27,7 @@ services:
|
|||
# See the volume section at the end of the file
|
||||
- erplibre_data_dir:/home/odoo/.local/share/Odoo
|
||||
- ./addons/addons:/ERPLibre/addons/addons
|
||||
- ./private:/ERPLibre/private
|
||||
- erplibre_conf:/etc/odoo
|
||||
restart: always
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ services:
|
|||
# See the volume section at the end of the file
|
||||
- erplibre_data_dir:/home/odoo/.local/share/Odoo
|
||||
- ./addons/addons:/ERPLibre/addons/addons
|
||||
- ./private:/ERPLibre/private
|
||||
- erplibre_conf:/etc/odoo
|
||||
restart: always
|
||||
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@
|
|||
<project name="openeducat_erp.git" path="addons.odoo16.0/openeducat_openeducat_erp" remote="openeducat" groups="addons"/>
|
||||
<project name="OpenUpgrade.git" path="script/OCA_OpenUpgrade" remote="OCA" clone-depth="10" groups="migration"/>
|
||||
<project name="operating-unit.git" path="addons.odoo16.0/OCA_operating-unit" remote="OCA" groups="addons"/>
|
||||
<project name="partner-contact.git" path="addons.odoo16.0/OCA_partner-contact" remote="OCA" groups="addons"/>
|
||||
<project name="partner-contact.git" path="addons.odoo16.0/OCA_partner-contact" remote="OCA" groups="addons,base"/>
|
||||
<project name="pos.git" path="addons.odoo16.0/OCA_pos" remote="OCA" groups="addons"/>
|
||||
<project name="product-attribute.git" path="addons.odoo16.0/OCA_product-attribute" remote="OCA" groups="addons"/>
|
||||
<project name="product-configurator.git" path="addons.odoo16.0/OCA_product-configurator" remote="OCA" groups="addons"/>
|
||||
|
|
@ -107,20 +107,20 @@
|
|||
<project name="project-agile.git" path="addons.odoo16.0/OCA_project-agile" remote="OCA" groups="addons"/>
|
||||
<project name="project.git" path="addons.odoo16.0/OCA_project" remote="OCA" groups="addons"/>
|
||||
<project name="purchase-workflow.git" path="addons.odoo16.0/OCA_purchase-workflow" remote="OCA" groups="addons"/>
|
||||
<project name="queue.git" path="addons.odoo16.0/OCA_queue" remote="OCA" groups="addons"/>
|
||||
<project name="queue.git" path="addons.odoo16.0/OCA_queue" remote="OCA" groups="addons,base"/>
|
||||
<project name="reporting-engine.git" path="addons.odoo16.0/OCA_reporting-engine" remote="OCA" groups="addons"/>
|
||||
<project name="rma.git" path="addons.odoo16.0/OCA_rma" remote="OCA" groups="addons"/>
|
||||
<project name="saas-addons.git" path="addons.odoo16.0/it-projects-llc_saas-addons" remote="it-projects-llc" groups="addons"/>
|
||||
<project name="sale-reporting.git" path="addons.odoo16.0/OCA_sale-reporting" remote="OCA" groups="addons"/>
|
||||
<project name="sale-workflow.git" path="addons.odoo16.0/OCA_sale-workflow" remote="OCA" groups="addons"/>
|
||||
<project name="server-auth.git" path="addons.odoo16.0/OCA_server-auth" remote="OCA" groups="addons"/>
|
||||
<project name="server-auth.git" path="addons.odoo16.0/OCA_server-auth" remote="OCA" groups="addons,base"/>
|
||||
<project name="server-backend.git" path="addons.odoo16.0/OCA_server-backend" remote="OCA" groups="addons"/>
|
||||
<project name="server-brand.git" path="addons.odoo16.0/OCA_server-brand" remote="OCA" groups="addons"/>
|
||||
<project name="server-brand.git" path="addons.odoo16.0/OCA_server-brand" remote="OCA" groups="addons,base"/>
|
||||
<project name="server-env.git" path="addons.odoo16.0/OCA_server-env" remote="OCA" groups="addons"/>
|
||||
<project name="server-tools.git" path="addons.odoo16.0/OCA_server-tools" remote="ERPLibre" revision="ERPLibre/16.0" groups="addons"/>
|
||||
<project name="server-ux.git" path="addons.odoo16.0/OCA_server-ux" remote="OCA" groups="addons"/>
|
||||
<project name="server-tools.git" path="addons.odoo16.0/OCA_server-tools" remote="ERPLibre" revision="ERPLibre/16.0" groups="addons,base"/>
|
||||
<project name="server-ux.git" path="addons.odoo16.0/OCA_server-ux" remote="OCA" groups="addons,base"/>
|
||||
<project name="shift-planning.git" path="addons.odoo16.0/OCA_shift-planning" remote="ERPLibre" revision="16.0_dev" groups="addons"/>
|
||||
<project name="social.git" path="addons.odoo16.0/OCA_social" remote="OCA" groups="addons"/>
|
||||
<project name="social.git" path="addons.odoo16.0/OCA_social" remote="OCA" groups="addons,base"/>
|
||||
<project name="survey.git" path="addons.odoo16.0/OCA_survey" remote="ERPLibre" revision="16.0_dev" groups="addons"/>
|
||||
<project name="stock-logistics-warehouse.git" path="addons.odoo16.0/OCA_stock-logistics-warehouse" remote="OCA" groups="addons"/>
|
||||
<project name="storage.git" path="addons.odoo16.0/OCA_storage" remote="OCA" groups="addons"/>
|
||||
|
|
@ -129,7 +129,7 @@
|
|||
<project name="vertical-hotel.git" path="addons.odoo16.0/OCA_vertical-hotel" remote="OCA" groups="addons"/>
|
||||
<project name="vertical-isp.git" path="addons.odoo16.0/OCA_vertical-isp" remote="OCA" groups="addons"/>
|
||||
<project name="vertical-travel.git" path="addons.odoo16.0/OCA_vertical-travel" remote="OCA" groups="addons"/>
|
||||
<project name="web.git" path="addons.odoo16.0/OCA_web" remote="OCA" groups="addons"/>
|
||||
<project name="web.git" path="addons.odoo16.0/OCA_web" remote="OCA" groups="addons,base"/>
|
||||
<project name="website-cms.git" path="addons.odoo16.0/OCA_website-cms" remote="OCA" groups="addons"/>
|
||||
<project name="website.git" path="addons.odoo16.0/OCA_website" remote="OCA" groups="addons"/>
|
||||
<project name="wms.git" path="addons.odoo16.0/OCA_wms" remote="OCA" groups="addons"/>
|
||||
|
|
|
|||
1
private/TODO.md
Normal file
1
private/TODO.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
Move your private file and project configuration here. The docker will share a volume with this repertory.
|
||||
0
private/__init__.py
Normal file
0
private/__init__.py
Normal file
|
|
@ -8,7 +8,13 @@ import random
|
|||
import re
|
||||
import sys
|
||||
import time
|
||||
import json
|
||||
import tempfile
|
||||
from subprocess import getoutput
|
||||
import tkinter as tk
|
||||
from tkinter import filedialog
|
||||
import getpass
|
||||
from pykeepass import PyKeePass
|
||||
|
||||
from randomwordfr import RandomWordFr
|
||||
from selenium import webdriver
|
||||
|
|
@ -20,16 +26,24 @@ from selenium.webdriver import ActionChains
|
|||
from selenium.webdriver.common.actions.wheel_input import ScrollOrigin
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.common.keys import Keys
|
||||
from selenium.webdriver.firefox.options import Options
|
||||
from selenium.webdriver.firefox.service import Service
|
||||
from selenium.webdriver.remote.webelement import WebElement
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
|
||||
# TODO maybe use TODO lib
|
||||
CONFIG_FILE = "./script/todo/todo.json"
|
||||
CONFIG_OVERRIDE_FILE = "./private/todo.json"
|
||||
LOGO_ASCII_FILE = "./script/todo/logo_ascii.txt"
|
||||
|
||||
|
||||
class SeleniumLib(object):
|
||||
def __init__(self, config):
|
||||
self.config = config
|
||||
self.kdbx = None
|
||||
self.video_recorder = None
|
||||
self.default_download_dir_path = tempfile.mkdtemp()
|
||||
if self.config.video_suffix:
|
||||
self.filename_recording = (
|
||||
f"video_{self.config.video_suffix}_"
|
||||
|
|
@ -67,6 +81,9 @@ class SeleniumLib(object):
|
|||
if not self.config.not_private_mode:
|
||||
firefox_options.add_argument("--private")
|
||||
|
||||
if self.config.headless:
|
||||
firefox_options.add_argument("--headless")
|
||||
|
||||
# firefox_options.set_preference("browser.link.open_newwindow", 3)
|
||||
# firefox_options.set_preference("browser.link.open_newwindow.restriction", 2)
|
||||
|
||||
|
|
@ -75,6 +92,18 @@ class SeleniumLib(object):
|
|||
firefox_options.set_preference(
|
||||
"permissions.default.desktop-notification", 1
|
||||
)
|
||||
firefox_options.set_preference("browser.download.folderList", 2)
|
||||
firefox_options.set_preference(
|
||||
"browser.download.manager.showWhenStarting", False
|
||||
)
|
||||
firefox_options.set_preference(
|
||||
"browser.download.dir", self.default_download_dir_path
|
||||
)
|
||||
firefox_options.set_preference(
|
||||
"browser.helperApps.neverAsk.saveToDisk",
|
||||
"application/octet-stream,application/pdf,application/x-pdf",
|
||||
)
|
||||
firefox_options.set_preference("pdfjs.disabled", True)
|
||||
firefox_services = None
|
||||
if self.config.firefox_binary_path:
|
||||
firefox_services = Service(
|
||||
|
|
@ -182,6 +211,53 @@ class SeleniumLib(object):
|
|||
self.driver.close()
|
||||
self.driver.switch_to.window(self.driver.window_handles[0])
|
||||
|
||||
def get_kdbx(self):
|
||||
if self.kdbx:
|
||||
return self.kdbx
|
||||
# Open file
|
||||
chemin_fichier_kdbx = self.get_config(["kdbx", "path"])
|
||||
if not chemin_fichier_kdbx:
|
||||
root = tk.Tk()
|
||||
root.withdraw() # Hide the main window
|
||||
chemin_fichier_kdbx = filedialog.askopenfilename(
|
||||
title="Select a File",
|
||||
filetypes=(("KeepassX files", "*.kdbx"),),
|
||||
)
|
||||
if not chemin_fichier_kdbx:
|
||||
# _logger.error(f"KDBX is not configured, please fill {CONFIG_FILE}")
|
||||
return
|
||||
|
||||
mot_de_passe_kdbx = self.get_config(["kdbx", "password"])
|
||||
if not mot_de_passe_kdbx:
|
||||
mot_de_passe_kdbx = getpass.getpass(
|
||||
prompt="Entrez votre mot de passe : "
|
||||
)
|
||||
|
||||
kp = PyKeePass(chemin_fichier_kdbx, password=mot_de_passe_kdbx)
|
||||
|
||||
if kp:
|
||||
self.kdbx = kp
|
||||
return kp
|
||||
|
||||
def get_config(self, lst_params):
|
||||
# Open file
|
||||
config_file = CONFIG_FILE
|
||||
if os.path.exists(CONFIG_OVERRIDE_FILE):
|
||||
config_file = CONFIG_OVERRIDE_FILE
|
||||
|
||||
with open(config_file) as cfg:
|
||||
dct_data = json.load(cfg)
|
||||
for param in lst_params:
|
||||
try:
|
||||
dct_data = dct_data[param]
|
||||
except KeyError:
|
||||
# _logger.error(
|
||||
# f"KeyError on file {config_file} with keys"
|
||||
# f" {lst_params}"
|
||||
# )
|
||||
return
|
||||
return dct_data
|
||||
|
||||
@staticmethod
|
||||
def get_french_word_no_space_no_accent():
|
||||
word = ""
|
||||
|
|
@ -248,6 +324,12 @@ class SeleniumLib(object):
|
|||
|
||||
return ele
|
||||
|
||||
def get_text_from_element(
|
||||
self, by: str = By.ID, value: str = None, timeout=5
|
||||
):
|
||||
ele = self.get_element(by, value, timeout=timeout)
|
||||
return ele.text
|
||||
|
||||
def get_all_element(self, by: str = By.ID, value: str = None, timeout=5):
|
||||
wait = WebDriverWait(self.driver, timeout)
|
||||
ele = wait.until(
|
||||
|
|
@ -1133,6 +1215,11 @@ def fill_parser(parser):
|
|||
action="store_true",
|
||||
help="Default is private mode.",
|
||||
)
|
||||
group_browser.add_argument(
|
||||
"--headless",
|
||||
action="store_true",
|
||||
help="For automation without GUI.",
|
||||
)
|
||||
group_browser.add_argument(
|
||||
"--no_dark_mode",
|
||||
action="store_true",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
TODO is an assistant robot to use ERPLibre
|
||||
Execute it with `./script/todo/todo.py` or `make todo`.
|
||||
|
||||
For a new project, copy todo_example.json to todo_override.json and edit it.
|
||||
For a new project, copy todo_example.json to private/todo.json and edit it.
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ except ModuleNotFoundError as e:
|
|||
_logger = logging.getLogger(__name__)
|
||||
|
||||
CONFIG_FILE = "./script/todo/todo.json"
|
||||
CONFIG_OVERRIDE_FILE = "./script/todo/todo_override.json"
|
||||
CONFIG_OVERRIDE_FILE = "./private/todo.json"
|
||||
LOGO_ASCII_FILE = "./script/todo/logo_ascii.txt"
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue