amélioration du programme en cas de nécessité de reprise du programme

This commit is contained in:
beren
2025-05-24 10:34:04 +00:00
parent 9b3979ab7f
commit a86002c924
3 changed files with 696 additions and 430 deletions

38
api.py
View File

@ -3,7 +3,33 @@ import base64
import requests
import ssl
from requests.adapters import HTTPAdapter
import logging
import os
from logging.handlers import TimedRotatingFileHandler
log_directory = "logs"
# 🔧 Configuration du handler avec rotation quotidienne
log_file = os.path.join(log_directory, "woocommerce.log")
handler = TimedRotatingFileHandler(
filename=log_file,
when="midnight", # ⏰ Rotation tous les jours à minuit
interval=1, # 📅 Chaque 1 jour
backupCount=7, # ♻️ Garde les 7 derniers fichiers de log
encoding='utf-8' # 🧾 Pour supporter tous les caractères
)
# 📋 Format du log
formatter = logging.Formatter(
fmt="%(asctime)s - %(levelname)s - %(message)s",
datefmt="%Y-%m-%d %H:%M:%S"
)
handler.setFormatter(formatter)
# 🔌 Récupère le logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG) # 👁 Niveau minimum à capturer
logger.addHandler(handler)
class WoocommerceApiClient(API):
def __init__(self, url, wc_consumer_key, wc_consumer_secret, wp_application_user, wp_application_password, verify_ssl=False, **kwargs):
@ -59,8 +85,8 @@ class WoocommerceApiClient(API):
try:
if self._is_wc_api(endpoint):
kwargs.update(self._get_requests_general_kwargs(endpoint))
print(kwargs) # ✅ Montre tout le dict
print(kwargs["headers"]) # ✅ Si tu veux un champ en particulier
#print(kwargs) # ✅ Montre tout le dict
#print(kwargs["headers"]) # ✅ Si tu veux un champ en particulier
return requests.get(**kwargs)
else:
return super().get(endpoint, **kwargs)
@ -83,7 +109,7 @@ class WoocommerceApiClient(API):
kwargs['files'] = files
if data:
kwargs['json'] = data
print("kwargs envoyés à requests.post:", kwargs)
#print("kwargs envoyés à requests.post:", kwargs)
response = requests.post(**kwargs)
elif self._is_wp_api(endpoint):
kwargs.update(self._get_requests_general_kwargs(endpoint))
@ -91,10 +117,14 @@ class WoocommerceApiClient(API):
response = requests.post(**kwargs)
else:
response = super().post(endpoint, data, **kwargs)
if response and response.status_code not in (500, 400):
if response.status_code not in (500, ) or retry >= self.max_retry:
return response
else:
retry += 1
logger.debug(f"status_code={response.status_code} - retry #{retry}")
except requests.exceptions.ConnectionError:
if retry < self.max_retry:
logger.debug(f"got requests.exceptions.ConnectionError - retry #{retry}")
print(".", end="")
retry += 1
else: raise

File diff suppressed because it is too large Load Diff

230
wcctl.py
View File

@ -3,44 +3,119 @@ import argparse
from woocommerce import API as WoocommerceApi
from api import WoocommerceApiClient
from api_woocommerce import AuthentificationWpApi, MediaManager, CategoryManager, ProductManager, AttributeManager, VariationsManager, TabManager, WooCommerceManager
import sys
from base64 import b64encode
import os, sys
from logging.handlers import TimedRotatingFileHandler
import logging
logger = logging.getLogger(__name__)
def import_medias_ods(args, media_manager):
if args.media:
if args.media_regex:
class WcCtlBase:
def __init__(self, args):
self.args = args
self._wcm = None
@property
def wcm(self):
if self._wcm is None:
wcapi = WoocommerceApiClient(
url=self.args.wc_url,
wc_consumer_key=self.args.wc_key,
wc_consumer_secret=self.args.wc_secret,
wp_application_user="admin_lcdm",
wp_application_password= "Do4p tLYF 5uje PF2M 21Zo x3OR", #"eAB4 49W6 ZRBj zIZc fH62 tv5c", #"yTW8 Mc6J FUCN tPSq bnuJ 0Sdw", #
wp_api=True,
version="wc/v3",
verify_ssl=True,
timeout=30
)
ath = AuthentificationWpApi()
media_manager = MediaManager(ath, wcapi, filename_ods=self.args.ods_path)
category_manager = CategoryManager(wcapi, ath, filename_ods=self.args.ods_path)
product_manager = ProductManager(wcapi, ath, filename_ods=self.args.ods_path)
attribute_manager = AttributeManager(wcapi, filename_ods=self.args.ods_path)
tab_manager = TabManager(wcapi, filename_ods=self.args.ods_path)
variation_manager = VariationsManager(wcapi, filename_ods=self.args.ods_path)
self._wcm = WooCommerceManager(wcapi=wcapi,
media_manager=media_manager,
category_manager=category_manager,
product_manager=product_manager,
tab_manager=tab_manager,
attribute_manager=attribute_manager,
variation_manager=variation_manager,
filename_ods=self.args.ods_path)
return self._wcm
class DeleteWcCtl(WcCtlBase):
def action(self):
logger.info(f"DeleteWcCtl:action({self.args}) - begin")
if self.args.all:
return self.wcm.delete_all_informations()
if self.args.attributes:
return None
class ImportOdsCtl(WcCtlBase):
def action(self):
logger.info(f"ImportOdsCtl:action({self.args}) - begin")
if self.args.media:
self.import_medias_ods()
if self.args.category:
medias = self.wmc.mm.get_all_as_slug_dict()
self.wmc.cm.medias = medias
regex = self.args.category_regex if self.args.category_regex else None
self.wcm.cm.update_data_categories(regex)
if self.args.attribute:
regex = self.args.attribute_regex if self.args.attribute_regex else None
self.wcm.am.create(regex)
self.wcm.am.configure_term()
if self.args.product:
self.import_products_ods()
if self.args.logo:
self.wcm.mm.assign_image_logo()
def import_medias_ods(self):
if self.args.media:
if self.args.media_regex:
try:
media_manager.upload_media(args.media_regex)
self.wcm.mm.upload_media(self.args.media_regex)
except ValueError:
print("error name product_regex")
elif args.media_range:
logger.error("error name product_regex")
elif self.args.media_range:
try:
parts = args.media_range.split(':')
parts = self.args.media_range.split(':')
start = int(parts[0]) -1 if parts[0] else 0
end = int(parts[1]) if len(parts) > 1 and parts[1] else None
print(f"start = {start}, end = {end or 'fin'}")
media_manager.upload_media_from_to(start, end)
logger.debug(f"start = {start}, end = {end or 'fin'}")
self.wcm.mm.upload_media_from_to(start, end)
except ValueError:
print("❌ Mauvais format pour --media-range. Utilisez par exemple --media-range=1:40")
else:
start, end = 0, None
print(" --media activé, mais aucune plage spécifiée.")
def import_products_ods(args, woocommerce_manager):
if args.product:
if args.product_regex:
def import_products_ods(self):
if self.args.product:
if self.args.product_regex:
try:
woocommerce_manager.process_file(args.product_regex)
self.wcm.process_file(self.args.product_regex)
except ValueError:
print("error name product_regex")
elif args.product_range:
elif self.args.product_range:
try:
parts = args.product_range.split(':')
parts = self.args.product_range.split(':')
start = int(parts[0]) -1 if parts[0] else 0
end = int(parts[1]) if len(parts) > 1 and parts[1] else None
print(f"start = {start}, end = {end or 'fin'}")
woocommerce_manager.process_file_from_to(start, end)
self.wcm.process_file_from_to(start, end)
except ValueError:
print("❌ Mauvais format pour --product-range. Utilisez par exemple --product-range=1:40")
else:
@ -48,14 +123,30 @@ def import_products_ods(args, woocommerce_manager):
print(" --product activé, mais aucune plage spécifiée.")
def main():
ath = AuthentificationWpApi()
# initialize logging
log_directory = "logs"
#ctx = ssl.create_default_context()
#ctx.set_ciphers('@SECLEVEL=2:ECDH+AESGCM:ECDH+CHACHA20:ECDH+AES:DHE+AES:AESGCM:!aNULL:!eNULL:!aDSS:!SHA1:!AESCCM:!PSK')
#http = urllib3.PoolManager(ssl_context=ctx)
#credentials = b64encode(f"{args.wc_key}:{args.wc_secret}").decode("utf-8")
# 🔧 Configuration du handler avec rotation quotidienne
log_file = os.path.join(log_directory, "woocommerce.log")
handler = TimedRotatingFileHandler(
filename=log_file,
when="midnight", # ⏰ Rotation tous les jours à minuit
interval=1, # 📅 Chaque 1 jour
backupCount=7, # ♻️ Garde les 7 derniers fichiers de log
encoding='utf-8' # 🧾 Pour supporter tous les caractères
)
# 📋 Format du log
formatter = logging.Formatter(
fmt="%(asctime)s - %(levelname)s - %(message)s",
datefmt="%Y-%m-%d %H:%M:%S"
)
handler.setFormatter(formatter)
# 🔌 Récupère le logger
logger.setLevel(logging.DEBUG) # 👁 Niveau minimum à capturer
logger.addHandler(handler)
parser = argparse.ArgumentParser(prog='wcctl', description='WooCommerce CLI controller')
@ -70,6 +161,10 @@ def main():
# 🧱 Sous-commandes
subparsers = parser.add_subparsers(dest='command', required=True)
delete_parser = subparsers.add_parser('delete', help='delete entities')
delete_parser.add_argument('--attributes', action="store_true", required=False, default=False, help='delete all attributes')
delete_parser.add_argument('--all', action='store_true', required=False, default=False, help='Delete media, categories, products, attributes, tabs')
# 📥 Commande : import-ods
import_parser = subparsers.add_parser('import-ods', help='Import ODS file data')
import_parser.add_argument('--ods-path', required=True, help='Path to the ODS file')
@ -97,10 +192,6 @@ def main():
import_parser.add_argument('--product-regex', type=str, help='Regex to filter and import product by name')
import_parser.add_argument('--product-range', type=str, help='Range of product rows to process (e.g., 10:30)')
# delete all informations
import_parser.add_argument('--delete-all', action='store_true', help='Delete media, categories, products, attributes, tabs')
# 📥 Commande : import-ods
checkssl_parser = subparsers.add_parser('checkssl', help='Check ssl connectivity')
check_parser = subparsers.add_parser('check', help='Check connectivity')
@ -110,27 +201,11 @@ def main():
# Analyse des arguments
args = parser.parse_args()
"""wcapi = WoocommerceApi(
url=args.wc_url,
consumer_key=args.wc_key,
consumer_secret=args.wc_secret,
wp_api=True,
version="wc/v3",
verify_ssl=False,
timeout=30
)"""
if args.command == "delete":
sys.exit(DeleteWcCtl(args).action())
wcapi = WoocommerceApiClient(
url=args.wc_url,
wc_consumer_key=args.wc_key,
wc_consumer_secret=args.wc_secret,
wp_application_user="admin_lcdm",
wp_application_password= "Do4p tLYF 5uje PF2M 21Zo x3OR", #"eAB4 49W6 ZRBj zIZc fH62 tv5c", #"yTW8 Mc6J FUCN tPSq bnuJ 0Sdw", #
wp_api=True,
version="wc/v3",
verify_ssl=True,
timeout=30
)
if args.command == "import-ods":
sys.exit(ImportOdsCtl(args).action())
if args.command == "check":
#wcctl-api-rw
@ -146,20 +221,6 @@ def main():
verify_ssl=True,
timeout=30
)
print("recupération d'un produit", end="")
response = wcapi.get("products", params={"per_page": 1, "page": 1})
print(response)
print("OK")
"""wcapi = WoocommerceApi(
url=args.wc_url,
consumer_key="wcctl-api-rw",
consumer_secret="NUrp R7tI oDKr FSqT hhf8 KxOT",
wp_api=True,
version="wp/v2",
verify_ssl=False,
timeout=30
)"""
print("recupération d'un media", end="")
response = wcapi.get("media", params={"per_page": 100, "page": 1})
print(response)
@ -173,53 +234,6 @@ def main():
print(f'connection OK')
sys.exit(0)
ath = AuthentificationWpApi()
media_manager = MediaManager(ath, wcapi, filename_ods=args.ods_path)
category_manager = CategoryManager(wcapi, ath, filename_ods=args.ods_path)
product_manager = ProductManager(wcapi, ath, filename_ods=args.ods_path)
attribute_manager = AttributeManager(wcapi, filename_ods=args.ods_path)
tab_manager = TabManager(wcapi, filename_ods=args.ods_path)
variation_manager = VariationsManager(wcapi, filename_ods=args.ods_path)
woocommerce_manager = WooCommerceManager(wcapi=wcapi,
media_manager=media_manager,
category_manager=category_manager,
product_manager=product_manager,
tab_manager=tab_manager,
attribute_manager=attribute_manager,
variation_manager=variation_manager,
filename_ods=args.ods_path)
# Dispatch en fonction de la commande
#if args.command == 'import-ods':
# import_medias_ods(args)
#print(f"🔍 args.media = {args.media}")
#print(f"🔍 args.media_range = {args.media_range}")
print(f"args = {args}")
if args.media:
import_medias_ods(args, media_manager)
if args.delete_all:
woocommerce_manager.delete_all_informations()
if args.category:
medias = media_manager.get_all_as_slug_dict()
category_manager.medias = medias
regex = args.category_regex if args.category_regex else None
category_manager.update_data_categories(regex)
if args.attribute:
regex = args.attribute_regex if args.attribute_regex else None
attribute_manager.create(regex)
attribute_manager.configure_term()
if args.product:
import_products_ods(args, woocommerce_manager)
if args.logo:
media_manager.assign_image_logo()
if __name__ == "__main__":
main()