Package corelibs¶
Note
Bienvenue dans la documentation de corelibs.
L’objectif de corelibs est d’agréger dans différents modules, toutes les fonctionnalités utiles pour simplifier nos travaux sans devoir tout réécrire à chaque fois…
Installation & Mise à jour¶
Note
Warning
Description générale Installation
Étapes pour installer le package corelibs:
lancer le terminal Anaconda ayant pour titre Anaconda Prompt (Anaconda3)
(base) C:\Users\kim>
dans Anaconda Prompt (Anaconda3) :
si besoin, lister les environnements existant
(base) C:\Users\kim>conda env list
activer l’environnement sur lequel est souhaité l’installation du package corelibs
(base) C:\Users\kim>conda activate nom_environnement
installer le package mkl-service récalcitrant, via le dépôt conda, canal conda-forge.
(nom_environnement) C:\Users\kim>conda install -c conda-forge mkl-service
installer le package corelibs
(nom_environnement) C:\Users\kim>pip install corelibs
Description générale Mise à jour
Étapes pour mettre à jour le package corelibs:
lancer le terminal Anaconda et dans Anaconda Prompt (Anaconda3)
activer l’environnement sur lequel est installé le package corelibs
(base) C:\Users\kim>conda activate nom_environnement
mettre à jour corelibs
(nom_environnement) C:\Users\kim>pip install corelibs -U
Interface Utilisateur¶
Description générale
corelibs a une interface utilisateur pour accéder plus rapidement à la documentation et certaines fonctionnalités, pour cela :
lancer le terminal Anaconda et dans Anaconda Prompt (Anaconda3)
activer l’environnement sur lequel est installé le package corelibs
(base) C:\Users\kim>conda activate nom_environnement
lancer l’interface corelibs avec la commande
(nom_environnement) C:\Users\kim>corelibs
qui affichera l’interface suivante

Configurations¶
Description générale
Ci-dessous sont listés l’ensemble des constantes définies et utilisées dans le package corelibs.
- Ces constantes peuvent être utilisées telles que définies ou écrasées à discrétion :
soit de manière globale, via le fichier user_config.py
soit localement, dans les programmes python appelants.
- L’ordre de recherche d’une constante est donc :
localement
user_config.py
config.py (le fichier de configuration de corelibs)
Dans le cas d’une constante simple, par exemple DEFAULT_LOGS_EXTENSION = ".log"
, corelibs utilisera la
version écrasée telle que redéfinie.
Dans le cas d’une constante plus complexe, de type dictionnaire, par exemple
DEFAULT_FIELD_STYLES = {
"asctime": {"color": 242, "bright": True},
"hostname": {"color": "magenta"},
"username": {"color": "yellow"},
"levelname": {"color": 242, "bright": True},
"name": {"color": "blue"},
"programname": {"color": "cyan"}
}
corelibs ne remplacera que les clés/valeurs redéfinies (i.e. les autres clés/valeurs seront gardées inchangées)
# Exemple instructions pour utiliser le fichier config utilisateur de manière globale et locale (portée au sein du programme actif)
import user_config as uc
print(uc.MA_CONSTANTE_UTILISATEUR) # affichera "Hello! =}"
# écrasement des constantes utilisateurs, avec une portée locale
uc.MA_CONSTANTE_UTILISATEUR = "Hello Kim ❤ =}"
print(uc.MA_CONSTANTE_UTILISATEUR) # affiche "Hello Kim ❤ =}"
# idem pour les constantes corelibs (attention à lire les documentations officielles tiers pour ne pas tout casser...)
DEFAULT_MIN_BYTE_SIZE_FORMAT = { # définition locale
"octet": {"min_size": 0},
"Ko": {"min_size": 1},
"Mo": {"min_size": 1},
"Go": {"min_size": 1},
"To": {"min_size": 1}
}
print(DEFAULT_MIN_BYTE_SIZE_FORMAT) # affiche {'octet': {'min_size': 0}, 'Ko': {'min_size': 1}, 'Mo': {'min_size': 1}, 'Go': {'min_size': 1}, 'To': {'min_size': 1}}
print(uc.DEFAULT_MIN_BYTE_SIZE_FORMAT) # {'octet': {'min_size': 0}, 'Ko': {'min_size': 1}, 'Mo': {'min_size': 1}, 'Go': {'min_size': 1}, 'To': {'min_size': 0.5}}
# Le fichier user_config.py se trouve dans le dossier caché nommé ".corelibs" se trouvant à :
# • %HOMEPATH%/.corelibs sous Windows
# • ~/.corelibs sous Linux
#
# accessible manuellement ou via l'interface graphique Corelibs avec la commande terminale
# $ corelibs
#
# ce fichier de configuration est modifiable à discrétion avec en particulier, la possibilité de rajouter des variables utilisateurs propres globalement vu par n'importe quel programme qui en fait l'import
Note
corelibs.lazy.open_explorer()

Warning
import logging as log
########################################################################################################################
# Bienvenue à... #
# ______ ___ __ #
# / ____/___ ________ / (_) /_ _____ #
# / / / __ \/ ___/ _ \/ / / __ \/ ___/ #
# / /___/ /_/ / / / __/ / / /_/ (__ ) #
# \____/\____/_/ \___/_/_/_.___/____/ #################
# # user_config.py #
########################################################################################################################
########################################################################################################################
# // * CONFIGURATION UTILISATEUR #######################################################################################
########################################################################################################################
# //? ici les nouvelles définitions/constantes utilisateur...
MA_CONSTANTE_UTILISATEUR = "Hello! =}"
########################################################################################################################
# /CONFIGURATION UTILISATEUR ###########################################################################################
########################################################################################################################
####################################
# DÉBUT CONFIGURATION CORELIBS... ###
########################################################################################################################
# // * CONFIGURATION INTERFACE UI ######################################################################################
########################################################################################################################
# //? Chemin pour le script Conda
# //? Windows 10: C:\Users\<your-username>\Anaconda3\
# //? macOS: /Users/<your-username>/anaconda3 for the shell install, ~/opt for the graphical install.
# //? Linux: /home/<your-username>/anaconda3
# //? cf. https://docs.anaconda.com/anaconda/user-guide/faq/ pour plus de détail
UI_CONDA_PATH = r"C:\ProgramData\Anaconda3\Scripts"
# //? Par défaut, le thème est aléatoire, pour connaitre le nom du thème affiché, mettre à Oui
UI_DISPLAY_THEME_NAME = False
# //? Nom du thème à afficher
UI_THEME_NAME = "Sandy Beach" # None pour un affichage aléatoire parmi la liste des thèmes ci-dessous
# Nom thèmes disponibles :
# "Black" "Blue Mono" "Blue Purple" "Bright Colors" "Brown Blue" "Dark" "Dark 2" "Dark Amber" "Dark Black"
# "Dark Black 1" "Dark Blue" "Dark Blue 1" "Dark Blue 2" "Dark Blue 3" "Dark Blue 4" "Dark Blue 5" "Dark Blue 6"
# "Dark Blue 7" "Dark Blue 8" "Dark Blue 9" "Dark Blue 10" "Dark Blue 11" "Dark Blue 12" "Dark Blue 13" "Dark Blue 14"
# "Dark Blue 15" "Dark Blue 16" "Dark Blue 17" "Dark Brown" "Dark Brown 1" "Dark Brown 2" "Dark Brown 3" "Dark Brown 4"
# "Dark Brown 5" "Dark Brown 6" "Dark Brown 7" "Dark Green" "Dark Green 1" "Dark Green 2" "Dark Green 3" "Dark Green 4"
# "Dark Green 5" "Dark Green 6" "Dark Green 7" "Dark Grey" "Dark Grey 1" "Dark Grey 2" "Dark Grey 3" "Dark Grey 4"
# "Dark Grey 5" "Dark Grey 6" "Dark Grey 7" "Dark Grey 8" "Dark Grey 9" "Dark Grey 10" "Dark Grey 11" "Dark Grey 12"
# "Dark Grey 13" "Dark Grey 14" "Dark Purple" "Dark Purple 1" "Dark Purple 2" "Dark Purple 3" "Dark Purple 4"
# "Dark Purple 5" "Dark Purple 6" "Dark Purple 7" "Dark Red" "Dark Red 1" "Dark Red 2" "Dark Tan Blue" "Dark Teal"
# "Dark Teal 1" "Dark Teal 2" "Dark Teal 3" "Dark Teal 4" "Dark Teal 5" "Dark Teal 6" "Dark Teal 7" "Dark Teal 8"
# "Dark Teal 9" "Dark Teal 10" "Dark Teal 11" "Dark Teal 12" "Default" "Default 1" "Default No More Nagging" "Green"
# "Green Mono" "Green Tan" "Hot Dog Stand" "Kayak" "Light Blue" "Light Blue 1" "Light Blue 2" "Light Blue 3"
# "Light Blue 4" "Light Blue 5" "Light Blue 6" "Light Blue 7" "Light Brown" "Light Brown 1" "Light Brown 2"
# "Light Brown 3" "Light Brown 4" "Light Brown 5" "Light Brown 6" "Light Brown 7" "Light Brown 8" "Light Brown 9"
# "Light Brown 10" "Light Brown 11" "Light Brown 12" "Light Brown 13" "Light Gray 1" "Light Green" "Light Green 1"
# "Light Green 2" "Light Green 3" "Light Green 4" "Light Green 5" "Light Green 6" "Light Green 7" "Light Green 8"
# "Light Green 9" "Light Green 10" "Light Grey" "Light Grey 1" "Light Grey 2" "Light Grey 3" "Light Grey 4"
# "Light Grey 5" "Light Grey 6" "Light Purple" "Light Teal" "Light Yellow" "Material 1" "Material 2" "Neutral Blue"
# "Purple" "Python" "Reddit" "Reds" "Sandy Beach" "System Default" "System Default 1" "System Default For Real" "Tan"
# "Tan Blue" "Teal Mono" "Topanga"
########################################################################################################################
# /CONFIGURATION INTERFACE UI ##########################################################################################
########################################################################################################################
########################################################################################################################
# // * CONFIGURATION LOCALE ############################################################################################
########################################################################################################################
# //? buffer de lecture/écriture en nombres d'octets
DEFAULT_BYTE_CHUNK_SIZE = 1048576 * 64 # 1048576 bytes <=> 1024KB <=> 1MB
# //? buffer de prévisualisation/lecture/écriture en nombre de lignes
DEFAULT_BUFFER_CHUNK_SIZE = 65536 # <=> max lignes Excel < 2007, sinon 1048576 lignes
# //? encodage par défaut des fichiers
DEFAULT_ENCODING_FILE = "latin-1" # //! Western Europe latin-1 pour les français, sinon choisir "utf-8" ou "ISO-8859-1"
# //? format français par défaut
DEFAULT_LOCALE_TIME = "fr" # //! en pour l'anglais => voir corelibs.lazy.get_locale_tab() pour la liste complète
# //? code page encoding pour les retour terminal des appels commandes DOS
DEFAULT_DOS_CMD_CP_ENCODING = "cp850" # cf. https://en.wikipedia.org/wiki/Code_page_850
# //? format des tailles avec leur valeur minimale pour l'affichage automatisé
DEFAULT_MIN_BYTE_SIZE_FORMAT = {
"octet": {"min_size": 0},
"Ko": {"min_size": 1},
"Mo": {"min_size": 1},
"Go": {"min_size": 1},
"To": {"min_size": 0.5}
}
########################################################################################################################
# /CONFIGURATION LOCALE ################################################################################################
########################################################################################################################
########################################################################################################################
# // * CONFIGURATION PROJET ############################################################################################
########################################################################################################################
# //? nom structures modèles de répertoires par défaut
DEFAULT_DIR_SCAFFOLDING = {
"input": { # dossier contenant toutes les données "entrées"
"name": "__INPUTS__",
"make": True
},
"output": { # dossier contenant toutes les données "sorties"
"name": "__OUTPUTS__",
"make": True
},
"logs": { # dossier contenant toutes les sorties "logs"
"name": "__LOGS__",
"make": True
},
"docs": { # dossier contenant toutes les documentations/specs liées au projet
"name": "__DOCS__",
"make": True
},
}
########################################################################################################################
# /CONFIGURATION PROJET ################################################################################################
########################################################################################################################
########################################################################################################################
# // * CONFIGURATION LOG ###############################################################################################
########################################################################################################################
# //? forcer l'exécution des instructions suivantes même quand une erreur est levée (Attention à son emploi...)
DEFAULT_IGNORE_ERROR = False
# //? affichage détaillé de la pile d'exécution
DEFAULT_STACK_TRACE = False
# //? redirection de l'affichage détaillé de la pile d'exécution vers la log
DEFAULT_STACK_TRACE_2_FILE = False
# //? affichage détaillé de la pile d'exécution
# par défaut, le style de couleur sera :
# • "lightbg" si environnement Jupyter, sinon "darkbg2" si DEFAULT_STACK_TRACE_2_FILE est faux
# • "plaintext" si DEFAULT_STACK_TRACE_2_FILE est vrai
DEFAULT_STYLE_STACK_TRACE = "default" # valeur possibles : plaintext, color, darkbg2 ou lightbg
# //? contexte du code source pour les affichage détaillés des logs
DEFAULT_CONTEXT_SOURCE_LINES = 3
# //? affichage informations en provenance du package corelibs
DEFAULT_VERBOSE = False
# //? nom fichier log par défaut dans le cas des entrées standards
DEFAULT_STDIN_LOGS_NAME = "_STDIN_"
# //? extension par défaut des fichiers logs
DEFAULT_LOGS_EXTENSION = ".log"
# //? niveau d"affichage des logs, valeurs possibles :
# * log.DEBUG <=> 10
# * log.INFO <=> 20 (valeur par défaut)
# * log.WARNING <=> 30
# * log.ERROR <=> 40
# * log.CRITICAL <=> 50
#
# //! pour désactiver une alerte, on augmente son niveau, par exemple WARNING (30)
# et dans ce cas, les alertes de niveau DEBUG et INFO seront ignorées.
DEFAULT_LOG_LEVEL = log.INFO # ou 20
# //? le style par défaut des LOG affichées dans la sortie standard
DEFAULT_FIELD_STYLES = {
"asctime": {"color": 242, "bright": True},
"hostname": {"color": "magenta"},
"username": {"color": "yellow"},
"levelname": {"color": 242, "bright": True},
"levelno": {"color": 242, "bright": True},
"lineno": {"color": "white"},
"process": {"color": "white"},
"name": {"color": "blue"},
"module": {"color": "blue"},
"programname": {"color": "cyan"},
"thread": {"color": "white"},
"filename": {"color": "blue"},
"funcName": {"color": "blue"},
}
# //? les couleurs par défaut selon le niveau
DEFAULT_LEVEL_STYLES = {
"critical": {
"color": 255,
"background": "red",
},
"error": {"color": "red"},
"warning": {"color": "yellow"},
"debug": {"color": "green"},
"info": {"color": "cyan"},
"notice": {"color": "magenta"},
"spam": {"color": "green"},
"success": {"color": "green"},
"verbose": {"color": "blue"},
}
# //? le label par défaut de la log
# si DEFAULT_SHORT_LOG_LABEL alors affiche simplement le nom du programme qui a généré la log
# sinon affichera le chemin complet avec le nom du programme source et cible qui ont levé l"info ou l"alerte
DEFAULT_SHORT_LOG_LABEL = True
# //? le format par défaut de la log
DEFAULT_LOG_FORMAT = \
"%(asctime)s %(username)s@%(hostname)s - %(name)s" \
+ " [P%(process)d - T%(thread)d - %(filename)s:%(lineno)05d] • %(levelname)13s : %(message)s"
# //? le timestamp par défaut de la log
DEFAULT_LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
########################################################################################################################
# /CONFIGURATION LOG ###################################################################################################
########################################################################################################################
Module log¶
Description générale
Module permettant de manipuler tout ce qui est relatif à la gestion des logs
-
class
corelibs.log.
ColorLog
(name=None, log_level=20, output_2_log_file=True, location=None, log_file_name=None, field_styles=None, level_styles=None, log_format=None, log_date_format=None)¶ Description
Classe de base pour manipuler les logs colorées sans distinctions en sortie terminal ou Jupyter Notebooks.cf. Installation & Mise à jour pour la configuration par défaut (modifiable lors de l’instanciation de la classe)
Note
ColorLog instancie dynamiquement la classe TermColorLog ou JupyterColorLog
- pour plus de détails concernant les arguments :
cf.
JupyterColorLog
cf.
TermColorLog
- Parameters
name –
indique le nom de la log en cours
valeur possibles: None/nom de la logvaleur par défaut: Nonelog_level –
indique le niveau minimum d’alerte pour l’affichage des logs
valeur possibles: None/niveau d’alertevaleur par défaut: config.DEFAULT_LOG_LEVELoutput_2_log_file –
indique s’il faut ou non écrire les logs dans un fichier en sortie
valeur possibles: False/Truevaleur par défaut: Truelocation –
indique l’emplacement des fichiers logs de sortie
valeur possibles: None/chemin dossier logsvaleur par défaut: None- Si location non renseigné, par défaut, les logs seront enregistrés dans le dossier retourné par
Sinon les logs seront enregistrés dans le dossier location\DEFAULT_DIR_SCAFFOLDING[“logs”][“name”]
log_file_name –
indique le nom de la log
valeur possibles: None/nom de la logvaleur par défaut: None- Si log_file_name non renseigné, par défaut, le nom sera la concaténation des retours de :
-
i.e. nom_programme_AAAAMMDD_HHMMDD.log, résultat de corelibs.lazy.get_file_extension(corelibs.lazy.get_module_name())[0] + “_” + corelibs.lazy.get_timestamp() + “.log”
field_styles –
permet de définir le style d’affichage des logs dans la sortie standard
valeur possibles: None/dictionnairevaleur par défaut: Nonelevel_styles –
permet de définir le style d’affichage des niveaux d’alerte des logs dans la sortie standard
valeur possibles: None/dictionnairevaleur par défaut: Nonelog_format –
permet de définir le format d’affichage de la log
valeur possibles: None/format d’affichage de la logvaleur par défaut: Nonelog_date_format –
permet de définir le format d’affichage horodaté de la log
valeur possibles: None/format d’affichage horodaté de la logvaleur par défaut: None
Note
- cf. Installation & Mise à jour :
DEFAULT_LOG_LEVEL
DEFAULT_FIELD_STYLES
DEFAULT_LEVEL_STYLES
DEFAULT_DIR_SCAFFOLDING
DEFAULT_LOGS_EXTENSION
DEFAULT_LOG_FORMAT
DEFAULT_LOG_DATE_FORMAT
Exemple :
# termcolorlog.py from corelibs import config, log # écrasement de la config par défaut de corelibs # config.DEFAULT_VERBOSE = True config.DEFAULT_LOGS_EXTENSION = ".LOG" # config.DEFAULT_SHORT_LOG_LABEL = False # config.DEFAULT_STACK_TRACE_2_FILE = True # config.DEFAULT_STYLE_STACK_TRACE = "plaintext" # config.DEFAULT_STACK_TRACE = True # config.DEFAULT_CONTEXT_SOURCE_LINES = 7 # instanciation par défaut pour la sortie standard terminal seulement cl = log.TermColorLog() cl.debug("Bonjour, ceci est un test niveau DEBUG") cl.info("Bonjour, ceci est un test niveau INFO", True) cl.warning("Bonjour, ceci est un test niveau WARNING") cl.error("Bonjour, ceci est un test niveau ERROR", trace_back=True) cl.critical("Bonjour, ceci est un test niveau CRITIQUE") # redéfinition du nom du dossier logs # /!\ IMPORTANT /!\ # il n'y a que le dossier des logs qui est pris en compte, définir les autres dossiers ici est inutile config.DEFAULT_DIR_SCAFFOLDING = { "logs": { # dossier contenant toutes les sorties "logs" "name": "__R2D2-LOGS__", "make": True }, } # instanciation personnalisée user_cl = log.TermColorLog( name="Ma log à moi que j'ai", log_level=None, output_2_log_file=True, location=r"D:\OneDrive\Documents\_TEST_\T32020", log_file_name=None, field_styles={ "asctime": {"color": "black"}, "name": {"color": "green"}, }, level_styles={ "info": { "color": "white", "background": "cyan" }, }, log_format="%(asctime)s - %(name)s [%(filename)s:%(lineno)07d] <> %(levelname)13s : %(message)s", log_date_format="%A %d %B %Y" ) user_cl.debug("Bonjour, ceci est un test personnalisé niveau DEBUG") user_cl.info("Bonjour, ceci est un test personnalisé niveau INFO") user_cl.warning("Bonjour, ceci est un test personnalisé niveau WARNING") user_cl.error("Bonjour, ceci est un test personnalisé niveau ERROR", trace_back=True) user_cl.critical("Bonjour, ceci est un test personnalisé niveau CRITIQUE", trace_back=True) # Création log dynamiquement selon contexte terminal standard ou Jupyter Notebooks xcl = log.ColorLog(log_file_name="KIM") xcl.debug("Bonjour, ceci est un test dynamique niveau DEBUG") xcl.info("Bonjour, ceci est un test dynamique niveau INFO") xcl.warning("Bonjour, ceci est un test dynamique niveau WARNING") xcl.error("Bonjour, ceci est un test dynamique niveau ERROR", trace_back=True) xcl.critical("Bonjour, ceci est un test dynamique niveau CRITIQUE", trace_back=True)
-
class
corelibs.log.
ColoredFormatter
(*args, colors: Optional[Dict[str, str]] = None, **kwargs)¶ Initialize the formatter with specified format strings.
Initialize the formatter either with the specified format string, or a default as described above. Allow for specialized date formatting with the optional datefmt argument. If datefmt is omitted, you get an ISO8601-like (or RFC 3339-like) format.
Use a style parameter of ‘%’, ‘{‘ or ‘$’ to specify that you want to use one of %-formatting,
str.format()
({}
) formatting orstring.Template
formatting in your format string.Changed in version 3.2: Added the
style
parameter.-
format
(record) → str¶ Format the specified record as text.
The record’s attribute dictionary is used as the operand to a string formatting operation which yields the returned string. Before formatting the dictionary, a couple of preparatory steps are carried out. The message attribute of the record is computed using LogRecord.getMessage(). If the formatting string uses the time (as determined by a call to usesTime(), formatTime() is called to format the event time. If there is exception information, it is formatted using formatException() and appended to the message.
-
-
class
corelibs.log.
JupyterColorLog
(log_level=20)¶ Description
Classe de base pour manipuler les logs colorées sur les sorties web Jupyter Notebooks.cf. Installation & Mise à jour pour la configuration par défaut (modifiable lors de l’instanciation de la classe)
- Parameters
log_level –
indique le niveau minimum d’alerte pour l’affichage des logs
valeur possibles: None/niveau d’alertevaleur par défaut: config.DEFAULT_LOG_LEVEL
Note
- cf. Installation & Mise à jour :
DEFAULT_LOG_LEVEL
Exemple :
# jupytercolorlog.py from corelibs import config, log # écrasement de la config par défaut de corelibs # config.DEFAULT_VERBOSE = True # config.DEFAULT_STACK_TRACE = True # config.DEFAULT_STYLE_STACK_TRACE = "color" # config.DEFAULT_CONTEXT_SOURCE_LINES = 7 # instanciation par défaut pour Jupyter Notebooks seuleemnt cl = log.JupyterColorLog() cl.debug("Bonjour, ceci est un test niveau DEBUG") cl.info("Bonjour, ceci est un test niveau INFO", trace_back=True) cl.warning("Bonjour, ceci est un test niveau WARNING") cl.error("Bonjour, ceci est un test niveau ERROR") cl.critical("Bonjour, ceci est un test niveau CRITIQUE") # Création log dynamiquement selon contexte terminal standard ou Jupyter Notebooks xcl = log.ColorLog() xcl.debug("Bonjour, ceci est un test dynamique niveau DEBUG") xcl.info("Bonjour, ceci est un test dynamique niveau INFO") xcl.warning("Bonjour, ceci est un test dynamique niveau WARNING") xcl.error("Bonjour, ceci est un test dynamique niveau ERROR") xcl.critical("Bonjour, ceci est un test dynamique niveau CRITIQUE")
-
class
corelibs.log.
StatusBars
(title=None, color='bold_cyan_on_white')¶ Description
Classe permettant de créer une barre d’état figée pour afficher dynamiquement les différentes étapes ou processus, ainsi que des barres de progression.Chaque barre de progression retour le temps intermédiaire passé par le processus ayant appelé cette barre de progression.La classe StatusBars donne également le temps d’exécution totalWarning
Les barres d’états ne fonctionnent que sur des terminaux et terminaux émulés (sous PyCharm par exemple voir Run > Edit Configurations… > Execution > Emulate terminal in output console)- Parameters
title – indique le titre à donner à la barre d’état
color –
indique la couleur souhaitée pour la barre d’état
valeur possibles: black, red, green, yellow, blue, magenta, cyan ou white (pour la couleur principale, comme pour la couleur du fond)Pour chaque couleur, il y a 3 états possibles, bold, bright et normal (qui est le nom simple de la couleur)
Chaque couleur peut être combinée une fois avec un état cité ci-dessus, l’état doit précéder le nom de la couleur
La couleur principale et la couleur de fond se combinent avec le mot on
Les mots sont liés par le caractère underscore _
Par exemple bold_black_on_bright_cyan
- Returns
- rien…
Exemple :
# statusbars.py # %% import random from corelibs import log # /!\ ATTENTION /!\ # Jupyter Notebook n'étant pas un terminal, il ne se passera rien... =} # Instanciations sb = log.StatusBars() cl = log.ColorLog(output_2_log_file=False, log_level=10) log_methods = { # dictionnaire avec les adresses des différentes méthode présentes dans TermColorLog 0: { "status": "success", "callback": cl.debug }, 1: { "status": "success", "callback": cl.info }, 2: { "status": "warning", "callback": cl.warning }, 3: { "status": "error", "callback": cl.error }, 4: { "status": "error", "callback": cl.critical } } message = "Hello, simple log dynamique avec un niveau aléatoire" # 1ère étape total_iteration = 53 desc_1 = sb.init_sub_process(color="cyan") # initialisation d'un sous process pour afficher les infos de la boucle pb_1 = sb.init_progress_bar(total=total_iteration, desc="1ère Étape :") # initialisation barre de progression for i in range(total_iteration): _ = random.choice(range(5)) log_methods[_]["callback"](f"{i} - {message}") # ici les logs ne sont pas rattachées donc l'affichage se fait en défilement normal dans le terminal... duree_etape = sb.update_progress_bar( pb_1, status_text=f"{(i + 1): >{2}}/{total_iteration} - Reste {(total_iteration - i - 1): >{2}}".rjust(26, " "), status=log_methods[_]["status"] ) sb.update_sub_process(desc_1, f"{i} - {message}") cl.info(duree_etape) # affichage durée 1ère étape # 2ème étape desc_2 = sb.init_sub_process(color="green", justify="left") # initialisation sous process 2ème étape sb.update_sub_process(desc_2, f"Coucou ceci est ma 2ème Étape et elle est affichée dans un sous process fils... " "Après la fin du (ou des) process qui me précède(nt) =}") # 3ème étape en erreur factor = 2 pb_2 = sb.init_progress_bar(total=total_iteration * factor, color="magenta", desc="3ème Étape :") for i in range(total_iteration * factor): duree_3_etape = sb.update_progress_bar(pb_2, f"{(i + 1): >{3}}/{total_iteration * factor}".rjust(23, " "), "error") cl.info(duree_3_etape) # affichage durée 3ème étape # 4ème étape en warning factor = 3 pb_3 = sb.init_progress_bar(total=total_iteration * factor, color="magenta", desc="4ème Étape :") for i in range(total_iteration * factor): duree_4_etape = sb.update_progress_bar(pb_3, f"{(i + 1): >{3}}/{total_iteration * factor}".rjust(23, " "), "warning") cl.info(duree_4_etape) # affichage durée 4ème étape # 5ème étape normale avec changement de couleur par défaut factor = 4 pb_4 = sb.init_progress_bar(total=total_iteration * factor, color="magenta", desc="5ème Étape :") for i in range(total_iteration * factor): duree_5_etape = sb.update_progress_bar(pb_4, f"{(i + 1): >{3}}/{total_iteration * factor}".rjust(23, " ") ) cl.info(duree_5_etape) # affichage durée 4ème étape duree_totale = sb.terminate() cl.info(duree_totale) # durée totale de statusbars.py
-
init_progress_bar
(total=100, desc='Avancement :', status_text='', display_status=True, color='green')¶ Description
Permet d’initialiser une nouvelle barre de progressionNote
Il n’y a pas de limitations aux nombres de barres de progression. Les affichages et utilisations de ces dernières sont ordonnés selon l’ordre d’appel de la méthode décrite ici- Parameters
total – indique le total des itérations
desc – indique la description à afficher pour la barre de progression
status_text – indique et précise le texte de l’état si nécessaire
display_status – indique l’affichage de l’état Succes/Warning/Error avec leur volumétrie totale
color – indique la couleur de la barre de progression
- Returns
- un descripteur
Exemple :
# progress_bar.py # %% from corelibs import log, tools # /!\ ATTENTION /!\ # Jupyter Notebook n'étant pas un terminal, il ne se passera rien... =} # Instanciations sb = log.StatusBars() cl = log.TermColorLog(output_2_log_file=False) # %% # Progress bar sur un fichier fichier = r"D:\OneDrive\Desktop\StockEtablissement_utf8\StockEtablissement_utf8_head_preview.csv" total_iteration = tools.get_total_lines_in_file(fichier) - 1 # dernière ligne à blanc comme dans tous fichiers plats pb_1 = sb.init_progress_bar(total=total_iteration - 1, color="magenta") # initialisation barre de progression with open(fichier) as f_in: for i, f in enumerate(f_in): cl.info(f"N° : {i} - Valeur lue : {f}") # ou process quelconque... duree_etape = sb.update_progress_bar( pb_1, status_text=f"{i + 1: >{3}}/{total_iteration - 1} - Reste {(total_iteration - i - 2): >{3}}" ) duree_totale = sb.terminate() cl.info(duree_totale)
-
init_sub_process
(title=None, color='white', fill=' ', justify='center')¶ Description
Permet d’initialiser une nouvelle ligne de barre d’état pour gérer un processus enfant. Chaque processus enfant peut hériter d’une ou plusieurs barre d’état en utilisatant son descripteurNote
Il n’y a pas de limitations aux nombres de sous-barres d’état. Les affichages et utilisations de ces dernières sont ordonnés selon l’ordre d’appel de la méthode décrite ici- Parameters
title – indique le titre de la nouvelle sous barre d’état
color – indique la couleur souhaitée pour le titre
fill – indique le caractère de remplissage
justify –
indique la justification du texte
valeur possibles: left, center ou right
- Returns
- un descripteur
-
terminate
()¶ Description
Permet de terminer l’instance StatusBars et renvoie le temps total d’exécution- Returns
- tuple nommé avec comme attributs :
duration
duration_in_second
-
update_progress_bar
(progress_bar_descriptor, status_text='', status='success', increment=1)¶ Description
Permet de mettre à jour la barre de progression- Parameters
progress_bar_descriptor – indique le descripteur retourné par la méthode
corelibs.log.StatusBars.init_progress_bar()
status_text – indique et précise le texte de l’état si nécessaire
status –
indique et précise l’état d’avancement
valeur possibles: success, warning, errorvaleur par défaut: successincrement – indique la valeur incrémentale
- Returns
- tuple nommé avec comme attributs :
duration
duration_in_second
-
update_sub_process
(sub_process_descriptor, phases)¶ Description
Permet de mettre à jour la sous-barre d’état- Parameters
sub_process_descriptor – indique le descripteur retourné par la méthode
corelibs.log.StatusBars.init_sub_process()
phases – indique et précise l’état si nécessaire
- Returns
- rien…
-
class
corelibs.log.
StopWatch
(log_handler=None, display_status_bar=False)¶ Description
Classe permettant de chronométrer un programme ou une portion de programmeLe niveau minimal pour afficher les informations doit être de
log.INFO
(cf. Installation & Mise à jour pour plus d’informations config.DEFAULT_LOG_LEVEL)- Parameters
log_handler – indique si le timing doit faire une sortie dans un fichier log, défini via l’instanciation de cf.
ColorLog
ou cf.TermColorLog
.display_status_bar –
indique s’il faut ou non afficher la barre de statut dans la sortie standard
valeur possibles: False/Truevaleur par défaut: False
- Returns
- rien…
Exemple :
# stopwatch.py from corelibs import log # Instanciation log cl = log.TermColorLog(output_2_log_file=False) # Instanciation Chronomètre sw = log.StopWatch(cl) # Ajout décorateur timing() pour calculer le temps d'exécution de la fonction `ma_fonction()` @log.timing() # Cumuler décorateur status_bar() pour afficher la barre de statut @log.status_bar() def ma_fonction(nb): for _ in range(nb): pass ma_fonction(200000000) ma_fonction(200000000) duration = sw.stop() # ici nous avons les infos sur la durée totale d'exécution... cl.info(duration)
-
stop
()¶ Description
méthode pour arrêter le chronomètre- Returns
- tuple nommé avec comme attributs :
duration
duration_in_second
-
class
corelibs.log.
TermColorLog
(name=None, log_level=20, output_2_log_file=True, location=None, log_file_name=None, field_styles=None, level_styles=None, log_format=None, log_date_format=None)¶ Description
Classe de base pour manipuler les logs colorées dans la sortie standard du terminal.cf. Installation & Mise à jour pour la configuration par défaut (modifiable lors de l’instanciation de la classe)
- Parameters
name –
indique le nom de la log en cours
valeur possibles: None/nom de la logvaleur par défaut: Nonelog_level –
indique le niveau minimum d’alerte pour l’affichage des logs
valeur possibles: None/niveau d’alertevaleur par défaut: config.DEFAULT_LOG_LEVELoutput_2_log_file –
indique s’il faut ou non écrire les logs dans un fichier en sortie
valeur possibles: False/Truevaleur par défaut: Truelocation –
indique l’emplacement des fichiers logs de sortie
valeur possibles: None/chemin dossier logsvaleur par défaut: None- Si location non renseigné, par défaut, les logs seront enregistrés dans le dossier retourné par
Sinon les logs seront enregistrés dans le dossier location\DEFAULT_DIR_SCAFFOLDING[“logs”][“name”]
log_file_name –
indique le nom de la log
valeur possibles: None/nom de la logvaleur par défaut: None- Si log_file_name non renseigné, par défaut, le nom sera la concaténation des retours de :
-
i.e. nom_programme_AAAAMMDD_HHMMDD.log, résultat de corelibs.lazy.get_file_extension(corelibs.lazy.get_module_name())[0] + “_” + corelibs.lazy.get_timestamp() + “.log”
field_styles –
permet de définir le style d’affichage des logs dans la sortie standard
valeur possibles: None/dictionnairevaleur par défaut: Nonelevel_styles –
permet de définir le style d’affichage des niveaux d’alerte des logs dans la sortie standard
valeur possibles: None/dictionnairevaleur par défaut: Nonelog_format –
permet de définir le format d’affichage de la log
valeur possibles: None/format d’affichage de la logvaleur par défaut: Nonelog_date_format –
permet de définir le format d’affichage horodaté de la log
valeur possibles: None/format d’affichage horodaté de la logvaleur par défaut: None
Note
- cf. Installation & Mise à jour :
DEFAULT_LOG_LEVEL
DEFAULT_FIELD_STYLES
DEFAULT_LEVEL_STYLES
DEFAULT_DIR_SCAFFOLDING
DEFAULT_LOGS_EXTENSION
DEFAULT_LOG_FORMAT
DEFAULT_LOG_DATE_FORMAT
Exemple :
# termcolorlog.py from corelibs import config, log # écrasement de la config par défaut de corelibs # config.DEFAULT_VERBOSE = True config.DEFAULT_LOGS_EXTENSION = ".LOG" # config.DEFAULT_SHORT_LOG_LABEL = False # config.DEFAULT_STACK_TRACE_2_FILE = True # config.DEFAULT_STYLE_STACK_TRACE = "plaintext" # config.DEFAULT_STACK_TRACE = True # config.DEFAULT_CONTEXT_SOURCE_LINES = 7 # instanciation par défaut pour la sortie standard terminal seulement cl = log.TermColorLog() cl.debug("Bonjour, ceci est un test niveau DEBUG") cl.info("Bonjour, ceci est un test niveau INFO", True) cl.warning("Bonjour, ceci est un test niveau WARNING") cl.error("Bonjour, ceci est un test niveau ERROR", trace_back=True) cl.critical("Bonjour, ceci est un test niveau CRITIQUE") # redéfinition du nom du dossier logs # /!\ IMPORTANT /!\ # il n'y a que le dossier des logs qui est pris en compte, définir les autres dossiers ici est inutile config.DEFAULT_DIR_SCAFFOLDING = { "logs": { # dossier contenant toutes les sorties "logs" "name": "__R2D2-LOGS__", "make": True }, } # instanciation personnalisée user_cl = log.TermColorLog( name="Ma log à moi que j'ai", log_level=None, output_2_log_file=True, location=r"D:\OneDrive\Documents\_TEST_\T32020", log_file_name=None, field_styles={ "asctime": {"color": "black"}, "name": {"color": "green"}, }, level_styles={ "info": { "color": "white", "background": "cyan" }, }, log_format="%(asctime)s - %(name)s [%(filename)s:%(lineno)07d] <> %(levelname)13s : %(message)s", log_date_format="%A %d %B %Y" ) user_cl.debug("Bonjour, ceci est un test personnalisé niveau DEBUG") user_cl.info("Bonjour, ceci est un test personnalisé niveau INFO") user_cl.warning("Bonjour, ceci est un test personnalisé niveau WARNING") user_cl.error("Bonjour, ceci est un test personnalisé niveau ERROR", trace_back=True) user_cl.critical("Bonjour, ceci est un test personnalisé niveau CRITIQUE", trace_back=True) # Création log dynamiquement selon contexte terminal standard ou Jupyter Notebooks xcl = log.ColorLog(log_file_name="KIM") xcl.debug("Bonjour, ceci est un test dynamique niveau DEBUG") xcl.info("Bonjour, ceci est un test dynamique niveau INFO") xcl.warning("Bonjour, ceci est un test dynamique niveau WARNING") xcl.error("Bonjour, ceci est un test dynamique niveau ERROR", trace_back=True) xcl.critical("Bonjour, ceci est un test dynamique niveau CRITIQUE", trace_back=True)
-
corelibs.log.
args_dumping
(wrapped_func)¶ Description
Décorateur pour lister tous les arguments passés dans une fonction décoréeLe niveau minimal pour afficher les informations doit être de
log.DEBUG
(cf. Installation & Mise à jour pour plus d’informations config.DEFAULT_LOG_LEVEL)Exemple :
# args_dumping.py from corelibs import config, log from random import randrange my_dict = { 0: { "nom": "MARIE ADÉLIE", "prénom": "Kim", "age": 7 }, 1: { "arg1": "Hello", "arg2": "Kim" }, 2: { "msg": "I ❤ U", "from": "papa" } } # le niveau d'alerte par défaut est à INFO, correspondant à la valeur 20... # 10 correspond à DEBUG, ce qui a pour effet d'afficher le dumping... config.DEFAULT_LOG_LEVEL = 10 # décommenter pour baisser le niveau d'alerte à DEBUG # décoration pour lister dynamiquement les arguments passés en paramétrage de la fonction `test_dumping(...) @log.args_dumping def test_dumping(iteration, *args, **kwargs): pass total_dict = len(my_dict) for i in range(7): # appel dynamique aléatoire d'arguments dans la fonction `test_dumping()` rand_number = randrange(total_dict) test_dumping( i, rand_number, "itération {i} et nb aléatoire {rand_number}".format(i="{:0>3}".format(i), rand_number=rand_number), sub_dict=my_dict[rand_number] )
-
corelibs.log.
dict_dumping
(wrapped_func)¶ Description
Décorateur pour afficher toutes les fonctions qui retournent un dictionnaire dans un but de vérification.Le niveau minimal pour afficher les informations doit être de
log.DEBUG
(cf. Installation & Mise à jour pour plus d’informations config.DEFAULT_LOG_LEVEL)Exemple :
# dict_dumping.py from corelibs import config, log, tools as to # le niveau d'alerte par défaut est à INFO, correspondant à la valeur 20... # 10 correspond à DEBUG, ce qui a pour effet d'afficher le dumping... config.DEFAULT_LOG_LEVEL = 10 # décommenter pour baisser le niveau d'alerte à DEBUG @log.dict_dumping def test_namedtuple(): filename = r"D:\OneDrive\Documents\_TEST_\2020-11-11.jpg" file_properties = to.get_file_properties(filename, pretty_byte_size=False) return file_properties # affichage simple du tuple nommé pas toujours évident à lire selon complexcité print(test_namedtuple()) # FileProperties(st_mode=33206, st_ino=11540474045256220, st_dev=3199390331, st_nlink=1, st_uid='Invités', st_gid=0, st_size=ByteSize(byte=98569, kilobyte=96.26, megabyte=0.09, gigabyte=0.0, terabyte=0.0), st_atime='14/11/2020 22:27:01', st_mtime='11/11/2020 22:10:46', st_ctime='11/11/2020 22:10:39') test_namedtuple()
-
corelibs.log.
progress_bar
(title=None, desc=None, desc_padding=32, color='green', terminate=False)¶ Description
Décorateur pour afficher l’avancement des différentes étapes process sous forme de barre de progression- Parameters
title – indique le titre de la barre
desc – indique la description à afficher pour la barre de progression
desc_padding – indique la taille de rembourrage
color – indique la couleur de la barre de progression
terminate – indique au décorateur de clore les descripteurs et de libérer le terminal pour un affichage normal
- Returns
- rien…
Exemple :
# progress_bar_decorator_version.py import time from corelibs import log cl = log.ColorLog(output_2_log_file=False) # Ajout décorateur status_bar() pour afficher des informations dans le terminal # /!\ ATTENTION /!\ # Jupyter Notebook n'étant pas un terminal, il ne se passera rien... =} @log.progress_bar(title="Ma barre d'état décorée", desc="Ma première étape", color="magenta", desc_padding=64) def ma_fonction_avec_barre_statut(nb): time.sleep(3) ma_fonction_avec_barre_statut(3) cl.info("Durée 1ère étape " + str(log.decorator_return["duration"]["progress_bar"])) print("\n") @log.progress_bar(color="cyan", desc_padding=64) # Sans titre... def ma_deuxieme_fonction_de_la_morkitu_avec_decorateur(): for _ in range(3): cl.info(f"{_: >3} : les informations défilent au dessus de la 2ème barre...") time.sleep(5) ma_deuxieme_fonction_de_la_morkitu_avec_decorateur() print("\n") cl.info("Durée 2ème étape " + str(log.decorator_return["duration"]["progress_bar"])) @log.progress_bar(terminate=True, color="white", desc_padding=64) # Ne pas oublier le terminate pour relâcher la barre d'état!!! def ma_derniere_fonction_avec_terminate(): time.sleep(7) ma_derniere_fonction_avec_terminate() cl.info("Durée dernière étape " + str(log.decorator_return["duration"]["progress_bar"])) cl.info("Durée Totale : " + log.decorator_return["duration"]["total"].duration) # Arrêt et fonctionnement normal à partir de maintenant... print("\n") for _ in range(3): print("hé "*((_+1)*2) + "... =}")
-
corelibs.log.
stack_trace
(force=False)¶ Description
Décorateur pour afficher le détail des piles d’exécution (dans le cadre d’un débug).- Parameters
force –
permet de forcer localement l’affichage détaillé
- cf. Installation & Mise à jour :
DEFAULT_STACK_TRACE
DEFAULT_CONTEXT_SOURCE_LINES
- Returns
- rien…
Exemple :
# stack_trace.py from corelibs import log, config # config.DEFAULT_STACK_TRACE = True # on force globalement l'affichage détaillé des piles d'exécution def palindrome(mot): mots = list(mot) len_mot = len(mots) for i in range(int(len_mot / 2) + 1): if mot[i].lower() != mot[(len_mot - 1) - i].lower(): return False return True @log.stack_trace(force=True) # on force localement l'affichage détaillé des piles d'exécution def is_palindrome(mot): if palindrome(mot): print("\"{mot}\" est un palindrome".format(mot=mot)) else: print("\"{mot}\" n'est pas un palindrome".format(mot=mot)) is_palindrome("Hello Kim, c'est papa =}") # False is_palindrome("saippuakauppias") # True
-
corelibs.log.
status_bar
(title=None)¶ Description
Décorateur pour figer sur le terminal, tout en bas, l’état d’avancement.La barre de statut n’existe que pendant le temps de l’exécution de la fonction décorée (i.e. lors de l’appel d’une autre fonction, cette barre disparait si cette dernière fonction n’est elle-même pas décorée).
- Parameters
title – permet de donner un label à la barre de statut
- Returns
- rien…
Exemple :
# statusbars_decorator.py from corelibs import log # Ajout décorateur status_bar() pour afficher des informations dans le terminal # /!\ ATTENTION /!\ # Jupyter Notebook n'étant pas un terminal, il ne se passera rien... =} @log.status_bar("Ma barre de statut figée") def ma_fonction_avec_barre_statut(nb): for _ in range(nb): print("{_} : les informations défilent au dessus de la 1ère barre...".format(_="{:0>3}".format(_))) ma_fonction_avec_barre_statut(3) print(log.decorator_return["duration"]["status_bar"]) # durée de l'étape status_bar print("\n") @log.status_bar() # Sans titre... def ma_deuxieme_fonction_de_la_morkitu_avec_decorateur(): for _ in range(3): print(f"{_: >3} : les informations défilent au dessus de la 2ème barre...") ma_deuxieme_fonction_de_la_morkitu_avec_decorateur() print(log.decorator_return["duration"]["status_bar"]) # durée de la seconde étape (car écrasement) # Arrêt et fonctionnement normal à partir de maintenant... print("\n") for _ in range(3): print("hé "*((_+1)*2) + "... =}")
-
corelibs.log.
timing
(log_handler=None)¶ Description
Décorateur pour chronométrer le temps d’exécution de toutes fonctions cibles- Parameters
log_handler – indique si le timing doit faire une sortie dans un fichier log, défini via l’instanciation de cf.
ColorLog
ou cf.TermColorLog
.- Returns
- rien…
Exemple :
# timing.py from corelibs import log from numba import njit cl = log.ColorLog() # 1. créer une instance de ColorLog() # Ajout décorateur timing() pour calculer le temps d'exécution de la fonction `ma_premiere_fonction_optimisee()` @log.timing() @njit() def ma_premiere_fonction_optimisee(nb): total = 0 for _ in range(nb): total = total + 1 return total cl.info( "le total est " + "{0:,}".format( ma_premiere_fonction_optimisee(30000000000) ).replace(",", " ") ) # Faire sortir le résultat du décorateur timing() dans un fichier log spécifique, ici, l'objet `cl` @log.timing(cl) def ma_deuxieme_fonction_non_optimisee(nb): # définition d'une 2ème fonction... total = 0 for _ in range(nb): total = total + 1 return total cl.info( "le total est " + "{0:,}".format( ma_deuxieme_fonction_non_optimisee(30000000000) ).replace(",", " ") )
Module lazy¶
Description générale
Module de base avec des fonctions, décorateurs utiles, etc…
-
corelibs.lazy.
add_dir_path_2_project
(path)¶ Description
Permet d’inclure dans le projet actuel des programmes python tiers, enregistrés dans un emplacement différent.Warning
En principe, il est très rare de faire appel à cette fonction. Si cela se répète, il faudrait éventuellement revoir la structure du projet.- Parameters
path – indique l’emplacement en chemin absolu du dossier contenant le ou les programmes python à inclure dans le projet actuel.
- Returns
- rien…
Exemple :
# D:\OneDrive\Documents\_TEST_\PY_2_IMPORT\programme_importe.py # Les instructions ci-dessous n'appartiennent pas au projet... et son emplacement source est D:\OneDrive\Documents\_TEST_\PY_2_IMPORT def say_hello(who): print("Hello", who)
# add_dir_path_2_project.py from corelibs import lazy as lz # inclusion du dossier parent contenant les programmes à inclure, ici D:\OneDrive\Documents\_TEST_\PY_2_IMPORT lz.add_dir_path_2_project(r"D:\OneDrive\Documents\_TEST_\PY_2_IMPORT") try: import programme_importe as pi except ImportError: raise Exception("\n\nProblème import programme tiers d'un emplacement loufoque, hors projet") pi.say_hello("Kim!") # affichera Hello Kim! si tout est OK
-
corelibs.lazy.
convert_2_dict
(obj)¶ Description
Permet de convertir tous les objets (convertissables) en dictionnaire de manière récursive.- Parameters
obj – objet à convertir
- Returns
- dictionnaireouobjet contenant un dictionnaire imbriqué converti
Exemple :
# convert_2_dict.py # %% from collections import namedtuple from corelibs import lazy as lz # création d'un objet PuPuce tuple nommé PuPuce = namedtuple("PuPuce", ["name", "age"]) kim = PuPuce( name="Kim", age=6 ) print(kim) # affiche PuPuce(name='Kim', age=6) print(lz.is_namedtuple_instance(kim)) # affiche bien True # %% # conversion en dictionnaire print(lz.convert_2_dict(kim)) # affiche {'name': 'Kim', 'age': 6} # %% # création d'un tuple nommé imbriqué NestedPuPuce = namedtuple("NestedPuPuce", ["name", "age", "nested_tuple"]) kim2 = NestedPuPuce( name="Kim", age=6, nested_tuple=kim ) print(kim2) # affiche NestedPuPuce(name='Kim', age=6, nested_tuple=PuPuce(name='Kim', age=6)) # %% # conversion en dictionnaire print(lz.convert_2_dict(kim2)) # {'name': 'Kim', 'age': 6, 'nested_tuple': {'name': 'Kim', 'age': 6}} # %% # tableau non convertissable print(lz.convert_2_dict(["TRUONG", "Kim", 6])) # ['TRUONG', 'Kim', 6] # %% # conversion d'un tuple nommé au sein du tableau... print(lz.convert_2_dict(["TRUONG", "Kim", 6, kim2])) # ['TRUONG', 'Kim', 6, {'name': 'Kim', 'age': 6, 'nested_tuple': {'name': 'Kim', 'age': 6}}]
-
corelibs.lazy.
copy
(source, destination)¶ Description
Permet de copier un ou des fichiers vers une nouvelle destination ou des nouvelles destinations. Les fichiers sont au sens Unix du terme (i.e. soit fichier régulier, soit répertoire)Warning
La copie lèvera une alerte si des sous répertoires destinations existent et portent les mêmes noms que les sous répertoire sources.- Parameters
source – indique l’emplacement source du ou des fichiers à copier avec le(s) chemin(s) absolu(s), avec ou sans schéma.
destination – indique l’emplacement destination du ou des fichiers à copier avec le(s) chemin(s) absolu(s).
- Returns
- rien…
Exemple :
# copy.py # %% from corelibs import lazy as lz # %% # Création dossier destination repertoire_destination = r"D:\OneDrive\Documents\_TEST_\_COPY_DESTINATION_" lz.mkdir(repertoire_destination, make_scaffolding=False) # %% # Copie simple de fichier standard, sans renommage lz.copy(r"\\wsl$\Ubuntu-20.04\root\.zsh_history", repertoire_destination) # chemin réseau... # %% # Copie simple de fichier standard, avec renommage lz.copy(r"D:\OneDrive\Documents\_TEST_\_éèçàoöôîïêëùûü;.txt", repertoire_destination + "\\nouveau_nom.txt") # %% # Copie simple de répertoire standard, sans renommage lz.copy(r"D:\OneDrive\Documents\_TEST_\__R2D2-LOGS__", repertoire_destination + "\\__R2D2-LOGS__") # IMPORTANT!!! remettre le même nom de dossier destination, autrement, la copie se fera au niveau du répertoire parent # %% # Copie simple de répertoire standard, avec renommage lz.copy(r"D:\OneDrive\Documents\_TEST_\__R2D2-LOGS__", repertoire_destination + "\\__R2D2__") # %% # Copie via mode modèle lz.copy(r"D:\OneDrive\Documents\_TEST_\*.sas*", repertoire_destination) # modèle avec extension # ou lz.copy(r"D:\OneDrive\Documents\_TEST_\*2020-11-11*", repertoire_destination) # modèle sans extension, comprenant la chaîne "2020-11-11" dans le nom # %% # Copie groupée dans un dossier lz.copy(( r"D:\OneDrive\Documents\_TEST_\*.sas*", # avec schéma r"D:\OneDrive\Documents\_TEST_\2020-11-11.jpg", r"D:\OneDrive\Documents\_TEST_\__R2D2-LOGS__" # dossier... ), repertoire_destination) # %% # Copie groupée d'une liste de fichiers dans une autre liste de fichiers (fonctionnement 1-1, i.e. même nombre de fichiers en entrée et en sortie, traitée de manière itérative) lz.copy(( r"D:\OneDrive\Documents\_TEST_\*.sas*", # avec schéma r"D:\OneDrive\Documents\_TEST_\2020-11-11.jpg", r"D:\OneDrive\Documents\_TEST_\__R2D2-LOGS__", # dossier... ), ( repertoire_destination, # sans renommage repertoire_destination + "\\2020-11-11_NOUVEAU_NOM.jpg", # avec renommage repertoire_destination + "\\__R2D2-NEW__", # avec renommage ))
-
corelibs.lazy.
datetime_2_epoch
(date_time, time_format='%d/%m/%Y %H:%M:%S', reference_epoch='Unix', ignore_errors=False)¶ Description
Permet de convertir une date/heure en nombre de secondes écoulés depuis le temps de référence epoch.cf.corelibs.lazy.epoch_2_datetime()
pour la conversion inverse- Parameters
date_time – date à convertir
time_format –
indique le format de la date et heure
valeur par défaut: “%d/%m/%Y %H:%M:%S” (DD/MM/AAAA HH:MM:SS)reference_epoch –
indique l’époque de référence
valeurs possibles: “Unix”, “Windows”valeur par défaut: “Unix”ignore_errors –
forcer l’exécution lorsqu’une erreur est levée
valeurs possibles: False/Truevaleur par défaut: False (cf. DEFAULT_IGNORE_ERROR dans Installation & Mise à jour)
- Returns
- timestamp au format epoch
Exemple :
# datetime_2_epoch.py # %% from corelibs import lazy as lz # conversion en epoch Unix (https://www.epochconverter.com/#tools) print(lz.datetime_2_epoch(date_time=" Oct 3 1978 1:33PM ", time_format="%b %d %Y %I:%M%p")) # même si ce type de chaîne loufoque est nettoyée avant le calcul, il est préférable d'écrire proprement la donnée... # 276269580000 print(lz.datetime_2_epoch("28/11/2013 19:23:52")) # 1385666632000 # conversion en epoch Windows (https://www.epochconverter.com/ldap) print(lz.datetime_2_epoch(date_time="Oct 3 1978 1:33PM", time_format="%b %d %Y %I:%M%p", reference_epoch="Windows")) # 119207431800000000 print(lz.datetime_2_epoch(date_time="28/11/2013 19:23:52", reference_epoch="Windows")) # 130301402320000000
-
corelibs.lazy.
delete_files
(file_path, extension='', remove_empty_dir=True, verbose=False)¶ Description
Permet de supprimer des fichiers ou répertoires récursivement. La suppression peut se faire également en se basant sur plusieurs extensions différentes (cf. exemple)- Parameters
file_path – le chemin absolu du fichier ou du répertoire à supprimer
extension –
le(s) extension(s) ou modèle des fichiers à supprimer
valeurs possibles: expression régulière pour désigner des extensions/modèles de nom de fichiersvaleur par défaut: rien (pour éviter les erreurs…)remove_empty_dir –
indique si il faut supprimer ou non le répertoire vidé
valeurs possibles: False/Truevaleur par défaut: Trueverbose –
afficher ou non les messages d’info/alertes
valeurs possibles: False/Truevaleur par défaut: DEFAULT_VERBOSE (cf. Installation & Mise à jour)
- Returns
- rien…
Exemple :
# delete_files.py # %% from corelibs import lazy as lz # %% # Suppression d'un fichier ciblé et nommé "Nouveau document texte.txt" file_2_del = r"D:\OneDrive\Documents\_TEST_\DosASupp\Nouveau document texte.txt" lz.delete_files(file_2_del, verbose=True) # %% # Suppression de tous les fichiers avec une extension .RTF files_2_del = r"D:\OneDrive\Documents\_TEST_\DosASupp" lz.delete_files(files_2_del, extension="*.rtf", verbose=True) # %% # Suppression de tous les fichiers avec une extension .DOC* et .XLS* files_2_del = r"D:\OneDrive\Documents\_TEST_\DosASupp" lz.delete_files(files_2_del, extension="*.doc*,*.xls*", verbose=True) # %% # L'extension peut prendre un modèle regex, par exemple : # Suppression de tous les fichiers ayant le mot _LOG_ dans le nom files_2_del = r"D:\OneDrive\Documents\_TEST_\DosASupp" lz.delete_files(files_2_del, extension="*_LOG_*", verbose=True) # %% # Suppression complète # • tous les fichiers à l'intérieur du dossier DosASupp # • une fois vide, le dossier DosASupp est supprimé folder_2_del = r"D:\OneDrive\Documents\_TEST_\DosASupp" lz.delete_files(folder_2_del, extension="*", verbose=True)
-
corelibs.lazy.
epoch_2_datetime
(seconds, time_format='%d/%m/%Y %H:%M:%S')¶ Description
Permet de convertir un nombre de secondes vers un format date/heure spécifié. L’epoch est le temps initial de référence, à partir duquel on mesure les secondes écoulées pour calculer les dates/heures. Sous UNIX/POSIX, ce temps correspond au 1 janvier 1970 00:00:00 UT et sous Windows NT, 1 janvier 1601 00:00:00 UT.cf.corelibs.lazy.datetime_2_epoch()
pour la conversion inverse- Parameters
seconds – indique le nombre de secondes
time_format –
indique le format de sortie souhaité
valeur par défaut: “%d/%m/%Y %H:%M:%S” (DD/MM/AAAA HH:MM:SS)
- Returns
- timestampouNone (si problème)
Exemple :
# epoch_2_datetime.py from corelibs import lazy as lz print(lz.epoch_2_datetime(1605050212)) # 11/11/2020 00:16:52
-
corelibs.lazy.
get_abspath
(root_dir_path, dir_2_join)¶ Description
Retourne le chemin absolu normalisé à partir d’un couple (chemin, dossier)- Parameters
root_dir_path – le chemin absolu
dir_2_join – le dosssier à concaténer au chemin absolu
- Returns
- le chemin normalisé
Exemple :
# get_abspath.py from corelibs import lazy as lz abs_path = lz.get_abspath(r"C:\documents/dir", "toto") print(f"Le chemin absolu normalisé est \"{abs_path}\"")
Terminal :
$ python get_abspath.py Le chemin absolu normalisé est "C:\documents\dir\toto"
-
corelibs.lazy.
get_bytes_size_4_human
(byte_size_format, default_format=None, min_byte_size_format={'Go': {'min_size': 1}, 'Ko': {'min_size': 1}, 'Mo': {'min_size': 1}, 'To': {'min_size': 0.5}, 'octet': {'min_size': 0}}, size_unit=True, ignore_errors=False)¶ Description
Permet de lister un tuple nommé contenant toutes les valeurs converties à partir d’une taille en octet.- Parameters
byte_size_format – tuple nommé calculé par
corelibs.lazy.get_bytes_size_formats()
default_format – format d’affichage souhaité | valeur par défaut: None, laissant le choix à la fonction de retourner la meilleure valeur | valeurs possible: “octet”, “Ko”, “Mo”, “Go” ou “To”
min_byte_size_format – lorsque le format d’affichage default_format est à None alors sera calculé automatiquement le meilleur format à afficher, dont les seuils minimums sont définis dans DEFAULT_MIN_BYTE_SIZE_FORMAT (cf. Installation & Mise à jour)
size_unit –
afficher l’unité de mesure
valeurs possibles: False/Truevaleur par défaut: Trueignore_errors –
forcer l’exécution lorsqu’une erreur est levée
valeurs possibles: False/Truevaleur par défaut: False (cf. DEFAULT_IGNORE_ERROR dans Installation & Mise à jour)
- Returns
- string sous la forme XX.XX Unité (où Unité est octet, Ko, Mo, Go ou To)oufloat (si l’unité de mesure n’est pas souhaitée)
Exemple :
# get_bytes_size_4_human.py # %% from corelibs import lazy as lz # %% byte_size = lz.get_bytes_size_formats(0) print(lz.get_bytes_size_4_human(byte_size)) # affiche par défaut la valeur 0 octet # %% byte_size = lz.get_bytes_size_formats(153800565) print(lz.get_bytes_size_4_human(byte_size)) # affiche par défaut la valeur 146.68 Mo # %% byte_size = lz.get_bytes_size_formats(1739886085) print(lz.get_bytes_size_4_human(byte_size)) # affiche par défaut la valeur 1.62 Go # %% # affichage forcé dans une unité de mesure souhaitée print(lz.get_bytes_size_4_human(byte_size, default_format="Mo")) # affiche 1 659.28 Mo # %% # affichage forcé en Mo, mais sans l'unité de mesure print(lz.get_bytes_size_4_human(byte_size, size_unit=False, default_format="Mo")) # affiche 1659.28
-
corelibs.lazy.
get_bytes_size_formats
(byte_size)¶ Description
Permet de lister un tuple nommé contenant toutes les valeurs converties à partir d’une taille en octet.- Parameters
byte_size – indique le nombre d’octets
- Returns
- tuple nommé avec comme attributs :
byte
kilobyte
megabyte
gigabyte
terabyte
Exemple :
# get_bytes_size_formats.py # %% from corelibs import lazy as lz print(lz.get_bytes_size_formats(0)) # affiche ByteSize(byte=0, kilobyte=0.0, megabyte=0.0, gigabyte=0.0, terabyte=0.0) print(lz.get_bytes_size_formats(153800565)) # affiche ByteSize(byte=153800565, kilobyte=150195.86, megabyte=146.68, gigabyte=0.14, terabyte=0.0) print(lz.get_bytes_size_formats(1739886085)) # affiche ByteSize(byte=1739886085, kilobyte=1699107.5, megabyte=1659.28, gigabyte=1.62, terabyte=0.0)
-
corelibs.lazy.
get_caller_line_number
(back_level=3, ignore_errors=False)¶ Description
Permet de connaître la ligne du module source appelant un autre module.- Parameters
back_level –
profondeur d’appel de la fonction parent/enfant
valeurs possibles: entiervaleur par défaut: 3ignore_errors –
forcer l’exécution lorsqu’une erreur est levée
valeurs possibles: False/Truevaleur par défaut: False (cf. DEFAULT_IGNORE_ERROR dans Installation & Mise à jour)
- Returns
ligne du module appelant
Exemple :
# get_caller_line_number.py # %% from corelibs import config, lazy as lz # appel croisé correct... def info(profondeur_appel=1): return lz.get_caller_line_number(profondeur_appel) print(f"Le numéro de la ligne du module appelant est {info(profondeur_appel=1)}") print(f"Le numéro de la ligne du module appelant est {info(profondeur_appel=2)}") # appel direct incorrect... lz.get_caller_line_number()
-
corelibs.lazy.
get_caller_module_name
()¶ Description
Permet de connaître le nom du module source appelant un autre module.- Returns
nom du module appelant
Exemple :
# get_caller_module_name.py from corelibs import lazy as lz def get_module_info(): caller_name = lz.get_caller_module_name() print(f"Le nom du module python appelant est \"{caller_name}\"")
# caller_module_name.py from tests.lazy import get_caller_module_name as gcmn gcmn.get_module_info()
Terminal :
$ python caller_module_name.py Le nom du module python appelant est "caller_module_name.py"
-
corelibs.lazy.
get_closest_value_in_list
(value, list_of_values, ignore_errors=False)¶ Description
Permet de récupérer la valeur la plus proche (en delta absolu) dans une liste de valeurs pour une valeur donnée.- Parameters
value – indique la valeur de référence
list_of_values – liste de valeurs (tuples ou tableaux)
ignore_errors –
forcer l’exécution lorsqu’une erreur est levée
valeurs possibles: False/Truevaleur par défaut: False (cf. DEFAULT_IGNORE_ERROR dans Installation & Mise à jour)
- Returns
- valeur la plus proche trouvée
Exemple :
# get_closest_value_in_list.py from corelibs import lazy as lz print( lz.get_closest_value_in_list(1.6, [1, 2, 3]) ) # retourne 2 qui est la valeur la plus proche de 1.6 en delta absolu print( lz.get_closest_value_in_list(74.7, (10, 20, 30, 40, 50, 60, 70, 80, 90, 100)) ) # retourne 70 array = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362] number = 103 print(lz.get_closest_value_in_list(number, array)) # retourne 122
-
corelibs.lazy.
get_dir_n_basename
(path)¶ Description
Retourne un tuple (chemin, nom fichier ou nom répertoire) à partir d’un chemin absolu normalisé (e.g. “C:\documents\dir” retournera “dir” et “C:\documents\dir\fichier.txt” retournera “fichier.txt”)- Parameters
path – chemin absolu normalisé
- Returns
- tuple nommé avec comme attributs :
dir_path
base_name
Exemple :
# get_dir_n_basename.py # %% from corelibs import lazy as lz # %% # chemin + fichier (si chemin seul, sera retourné alors le nom du dossier + le chemin amenant au dossier) dir_n_basename = lz.get_dir_n_basename(r"C:\Users\M47624\corelibs\tests\lazy\get_dir_n_basename.py") # récupération par index print("Le chemin est \"{dir}\"".format(dir=dir_n_basename[0])) print("Le fichier est \"{base}\"".format(base=dir_n_basename[1])) # %% # récupération par attributs print("Le chemin est \"{dir}\"".format(dir=dir_n_basename.dir_path)) print("Le fichier est \"{base}\"".format(base=dir_n_basename.base_name)) # %% # sortie "séparée" ou "déballée" (unpacked) dir, base = lz.get_dir_n_basename(r"C:\Users\M47624\corelibs\tests\lazy\get_dir_n_basename.py") print("Le chemin est \"{dir}\"".format(dir=dir)) print("Le fichier est \"{base}\"".format(base=base))
Terminal :
$ python get_dir_n_basename.py Le chemin est "C:\Users\M47624\corelibs\tests\lazy" Le fichier est "get_dir_n_basename.py" Le chemin est "C:\Users\M47624\corelibs\tests\lazy" Le fichier est "get_dir_n_basename.py" Le chemin est "C:\Users\M47624\corelibs\tests\lazy" Le fichier est "get_dir_n_basename.py"
-
corelibs.lazy.
get_file_extension
(filename, extensions=True, split_extensions=False)¶ Description
Retourne un tuple (nom fichier, .extension(s))- Parameters
filename – nom du fichier avec extension (avec ou sans chemin)
extensions –
précise si le fichier comporte des extensions composites ou non (e.g. “.tar.gz”)
valeurs possibles: False/Truevaleur par défaut: Truesplit_extensions –
dans le cas d’une extension composite (e.g. “.tar.gz”) renvoie soit une chaine de caractère (i.e. “.tar.gz”), soit un tableau d’extensions (i.e. [“.tar”, “.gz”])
valeurs possibles: False/Truevaleur par défaut: False (renvoie par défaut une chaine d’extensions composites)
- Returns
- tuple nommé avec comme attributs :
file_name
file_extension
Exemple :
# get_file_extension.py # %% from corelibs import lazy as lz # %% stem, suffix = lz.get_file_extension(r"\\file\path\file name.tar.gz") print(f"Le nom du fichier sans extension est \"{stem}\"") # Le nom du fichier sans extension est "file name" # %% print(f"Le nom de l'extension par défaut est \"{suffix}\"") # Le nom de l'extension par défaut est ".tar.gz" # %% stem, suffix = lz.get_file_extension(r"\\file\path\file name.tar.gz", split_extensions=True) print("Le nom du fichier sans extension est \"{stem}\"".format(stem=stem)) # Le nom du fichier sans extension est "file name" # %% print("Le tableau des extensions est \"{suffix}\"".format(suffix=suffix)) # Le tableau des extensions est "['.tar', '.gz']" # %% file_properties = lz.get_file_extension(r"\\file\path\file name.tar.gz", split_extensions=True) print("Le nom du fichier sans extension est \"{stem}\"".format(stem=file_properties.file_name)) # Le nom du fichier sans extension est "file name" # %% print("Le tableau des extensions est \"{suffix}\"".format(suffix=file_properties.file_extension)) # Le tableau des extensions est "['.tar', '.gz']"
-
corelibs.lazy.
get_home
()¶ Description
Permet de retrouver le chemin de l’utilisateur (“home”)- Returns
- le chemin absolu du home
Exemple :
# get_home.py from corelibs import lazy as lz print(lz.get_home())
-
corelibs.lazy.
get_hostname
()¶ Description
Récupère le nom de l’ordinateur courant- Returns
- nom de l’ordinateur courant
Exemple :
# get_hostname.py from corelibs import config, lazy as lz hostname = lz.get_hostname() print("Le nom de l'ordinateur actuel est \"{hostname}\"".format(hostname=hostname))
-
corelibs.lazy.
get_locale_tab
(platform_os=None, yaml_dumping=True)¶ Description
Liste l’ensemble des codes langues disponibles pour l’internationalisation (utilisé parcorelibs.cleanse.is_datetime()
ou par le builtin locale.setlocale(…) => cf. documentation officielle python)- Parameters
platform_os –
indique quel est la plateforme de référence à vérifier
valeurs possibles: “Windows”, “Unix”, “All” ou “None”valeur par défaut: “None”yaml_dumping – indique s’il faut afficher de manière lisible ou retourner la liste
- Returns
- liste des codes si yaml_dumping == False
Exemple :
# get_locale_tab.py # %% from corelibs import lazy as lz # %% # Affichage sous une forme lisible pour un humain # Afficher la liste des codes langues disponibles par défaut (détection de l'OS) lz.get_locale_tab() # Forcer l'affichage pour toutes les plateformes disponibles lz.get_locale_tab(platform_os="all") # Afficher la liste pour Windows lz.get_locale_tab(platform_os="Windows") # Afficher la liste pour Unix lz.get_locale_tab(platform_os="Unix") # %% # Récupération de la liste dans une variable locale_tab_list = lz.get_locale_tab(platform_os="all", yaml_dumping=False) print(locale_tab_list["Windows"]["fr"]) # affichera français (France)
-
corelibs.lazy.
get_module_name
()¶ Description
Retourne le nom du module courant- Returns
nom module courant
Exemple :
# get_module_name.py from corelibs import lazy as lz module_name = lz.get_module_name() print("Le nom du module python est \"{module_name}\"".format(module_name=module_name))
-
corelibs.lazy.
get_module_path
()¶ Description
Retourne le chemin du script/programme python courant- Returns
- os.path.realpath(sys.argv[0])ouos.path.dirname(os.path.realpath(sys.argv[0])))
Exemple :
# get_module_path.py from corelibs import lazy as lz path = lz.get_module_path() print("Le chemin du programme python est \"{path}\"".format(path=path))
Terminal :
$ python get_module_path.py Le chemin du programme python est "C:\Users\M47624\corelibs\tests\lazy"
-
corelibs.lazy.
get_path_docs_dir
(location=None)¶ Description
Retourne le chemin absolu du répertoire des docs/specs, nommé par défaut “__DOCS__” cf.corelibs.lazy.mkdir()
pour plus de détails.- Parameters
location –
la location du répertoire racine contenant le répertoire des docs/specs.
valeur par défaut: le chemin retourné parcorelibs.lazy.get_module_path()
- Returns
- chemin absolu du répertoire “__DOCS__” (si existe, e.g. “C:\Users\M47624\__DOCS__”)ouchaîne vide (sinon)
Exemple :
# get_path_docs_dir.py from corelibs import config, lazy as lz root_path = r"D:\OneDrive\Documents\_TEST_\PARENTS\INEXISTANTS" print(lz.get_path_docs_dir(root_path)) # retourne rien lz.mkdir( root_path, dir_scaffolding={ "input": { # dossier contenant toutes les données "entrées" "name": "__R2 D2__", "make": False }, "output": { # dossier contenant toutes les données "sorties" "name": "__MY_OUTPUTS__", "make": False }, "logs": { # dossier contenant toutes les sorties "logs" "name": "__MY-LOGS__", "make": False }, "docs": { # dossier contenant toutes les documentations/specs liées au projet "name": "__SPECS__", "make": True }, }, verbose=False ) print(lz.get_path_docs_dir(root_path)) # retourne "D:\OneDrive\Documents\_TEST_\PARENTS\INEXISTANTS\__SPECS__"
-
corelibs.lazy.
get_path_input_dir
(location=None)¶ Description
Retourne le chemin absolu du répertoire des entrées, nommé par défaut “__INPUTS__” cf.corelibs.lazy.mkdir()
pour plus de détails.- Parameters
location –
la location du répertoire racine contenant le répertoire des entrées.
valeur par défaut: le chemin retourné parcorelibs.lazy.get_module_path()
- Returns
- chemin absolu du répertoire “__INPUTS__” (si existe, e.g. “C:\Users\M47624\__INPUTS__”)ouchaîne vide (sinon)
Exemple :
# get_path_input_dir.py from corelibs import config, lazy as lz root_path = r"D:\OneDrive\Documents\_TEST_\PARENTS\INEXISTANTS" print(lz.get_path_input_dir(root_path)) # retourne rien lz.mkdir( root_path, dir_scaffolding={ "input": { # dossier contenant toutes les données "entrées" "name": "__R2 D2__", "make": True }, "output": { # dossier contenant toutes les données "sorties" "name": "__MY_OUTPUTS__", "make": False }, "logs": { # dossier contenant toutes les sorties "logs" "name": "__MY-LOGS__", "make": False }, "docs": { # dossier contenant toutes les documentations/specs liées au projet "name": "__DOCS__", "make": False }, }, verbose=False ) print(lz.get_path_input_dir(root_path)) # retourne "D:\OneDrive\Documents\_TEST_\PARENTS\INEXISTANTS\__R2 D2__"
-
corelibs.lazy.
get_path_logs_dir
(location=None)¶ Description
Retourne le chemin absolu du répertoire des logs, nommé par défaut “__LOGS__” cf.corelibs.lazy.mkdir()
pour plus de détails.- Parameters
location –
la location du répertoire racine contenant le répertoire des logs.
valeur par défaut: le chemin retourné parcorelibs.lazy.get_module_path()
- Returns
- chemin absolu du répertoire “__LOGS__” (si existe, e.g. “C:\Users\M47624\__LOGS__”)ouchaîne vide (sinon)
Exemple :
# get_path_logs_dir.py from corelibs import config, lazy as lz root_path = r"D:\OneDrive\Documents\_TEST_\PARENTS\INEXISTANTS" print(lz.get_path_logs_dir(root_path)) # retourne rien lz.mkdir( root_path, dir_scaffolding={ "input": { # dossier contenant toutes les données "entrées" "name": "__R2 D2__", "make": False }, "output": { # dossier contenant toutes les données "sorties" "name": "__MY_OUTPUTS__", "make": False }, "logs": { # dossier contenant toutes les sorties "logs" "name": "__MY-LOGS__", "make": True }, "docs": { # dossier contenant toutes les documentations/specs liées au projet "name": "__DOCS__", "make": False }, }, verbose=False ) print(lz.get_path_logs_dir(root_path)) # retourne "D:\OneDrive\Documents\_TEST_\PARENTS\INEXISTANTS\__MY_LOGS__"
-
corelibs.lazy.
get_path_output_dir
(location=None)¶ Description
Retourne le chemin absolu du répertoire des sorties, nommé par défaut “__OUTPUTS__” cf.corelibs.lazy.mkdir()
pour plus de détails.- Parameters
location –
la location du répertoire racine contenant le répertoire des sorties.
valeur par défaut: le chemin retourné parcorelibs.lazy.get_module_path()
- Returns
- chemin absolu du répertoire “__OUTPUTS__” (si existe, e.g. “C:\Users\M47624\__OUTPUTS__”)ouchaîne vide (sinon)
Exemple :
# get_path_output_dir.py from corelibs import config, lazy as lz root_path = r"D:\OneDrive\Documents\_TEST_\PARENTS\INEXISTANTS" print(lz.get_path_output_dir(root_path)) # retourne rien lz.mkdir( root_path, dir_scaffolding={ "input": { # dossier contenant toutes les données "entrées" "name": "__R2 D2__", "make": False }, "output": { # dossier contenant toutes les données "sorties" "name": "__MY_OUTPUTS__", "make": True }, "logs": { # dossier contenant toutes les sorties "logs" "name": "__MY-LOGS__", "make": False }, "docs": { # dossier contenant toutes les documentations/specs liées au projet "name": "__DOCS__", "make": False }, }, verbose=False ) print(lz.get_path_output_dir(root_path)) # retourne "D:\OneDrive\Documents\_TEST_\PARENTS\INEXISTANTS\__MY_OUTPUTS__"
-
corelibs.lazy.
get_path_scaffold_directories
(location=None)¶ Description
Retourne les chemins absolus de tous les répertoires créés cf.corelibs.lazy.mkdir()
pour plus de détails.- Parameters
location –
la location du répertoire racine contenant les répertoires modèles.
valeur par défaut: le chemin retourné parcorelibs.lazy.get_module_path()
- Returns
- tuple nommé avec comme attributs :
docs : chemin absolu du répertoire “__DOCS__” (si existe)
input : chemin absolu du répertoire “__INPUTS__” (si existe)
output : chemin absolu du répertoire “__OUTPUTS__” (si existe)
logs : chemin absolu du répertoire “__LOGS__” (si existe)
Exemple :
# get_path_scaffold_directories.py # %% from corelibs import config, lazy as lz root_path = r"D:\OneDrive\Documents\_TEST_\PARENTS\INEXISTANTS" print(lz.get_path_scaffold_directories(root_path)) # retourne None lz.mkdir( root_path, dir_scaffolding={ "input": { # dossier contenant toutes les données "entrées" "name": "__R2 D2__", "make": True }, "output": { # dossier contenant toutes les données "sorties" "name": "__MY_OUTPUTS__", "make": True }, "logs": { # dossier contenant toutes les sorties "logs" "name": "__MY-LOGS__", "make": True }, "docs": { # dossier contenant toutes les documentations/specs liées au projet "name": "__DOCUMENTATIONS__", "make": True }, }, verbose=False ) scaffold_dir_path = lz.get_path_scaffold_directories(root_path) print(scaffold_dir_path) # récupréer les chemins des docs print(scaffold_dir_path.docs) # récupréer les chemins des inputs print(scaffold_dir_path.input) # récupréer les chemins des outputs print(scaffold_dir_path.output) # récupréer les chemins des logs print(scaffold_dir_path.logs) # %% # si le définition est écrasée, alors le get_path_scaffold_directories() va tenter de retrouver les nouvelles # informations, par exemple ci-dessous, le nouveau nom du répertoire "input" s'appellera "__R2 D2__" et ainsi de suite config.DEFAULT_DIR_SCAFFOLDING = { "input": { # dossier contenant toutes les données "entrées" "name": "__R2 D2__", "make": False }, "output": { # dossier contenant toutes les données "sorties" "name": "__MY_OUTPUTS__", "make": False }, "logs": { # dossier contenant toutes les sorties "logs" "name": "__MY-LOGS__", "make": True }, "docs": { # dossier contenant toutes les documentations/specs liées au projet "name": "__DOCS__", "make": False }, } print(lz.get_path_scaffold_directories(root_path)) # affichera # ScaffoldDir(input='D:\\OneDrive\\Documents\\_TEST_\\PARENTS\\INEXISTANTS\\__R2 D2__', output='D:\\OneDrive\\Documents\\_TEST_\\PARENTS\\INEXISTANTS\\__MY_OUTPUTS__', logs='D:\\OneDrive\\Documents\\_TEST_\\PARENTS\\INEXISTANTS\\__MY-LOGS__', docs='') # "docs" est vide car nous cherchons un nom "__DOCS__" alors que nous avons créé "__DOCUMENTATIONS__"
-
corelibs.lazy.
get_timestamp
(timestamp_format='DT', display_ms=False, only_ms=False)¶ Description
Retourne un timestamp normalisé ; utile pour suffixer les noms des fichiers- Parameters
timestamp_format – timestamp_format souhaité du timestamp | valeurs possibles: DT, D, T, NOW, GD ou GT | valeur par défaut: DT
display_ms –
afficher ou non les milli secondes
valeurs possibles: False/Truevaleur par défaut: Falseonly_ms –
récupère seulement les millièmes de secondes (pratique si besoin d’un seed)
valeurs possibles: False/Truevaleur par défaut: False
- Returns
- timestamp, selon timestamp_format :* YYYYMMDD_HHMMSS.SSSSSS* YYYYMMDD_HHMMSS* ou SSSSSS
Exemple :
# get_timestamp.py # %% from corelibs import lazy as lz # %% timestamp = lz.get_timestamp() print("Le timestamp sans milli secondes est {timestamp}".format(timestamp=timestamp)) # Le timestamp sans milli secondes est 20201209_181434 # %% timestamp = lz.get_timestamp(only_ms=True) print("Le timestamp en milli secondes est {timestamp}".format(timestamp=timestamp)) # Le timestamp en milli secondes est 096248 # %% timestamp = lz.get_timestamp(display_ms=True) print("Le timestamp avec milli secondes est {timestamp}".format(timestamp=timestamp)) # Le timestamp avec milli secondes est 20201209_181434.097248 # %% timestamp = lz.get_timestamp(timestamp_format="D") print("Le timestamp avec la date seulement est {timestamp}".format(timestamp=timestamp)) # Le timestamp avec la date seulement est 20201209 # %% timestamp = lz.get_timestamp(timestamp_format="T") print("Le timestamp avec l'heure seulement est {timestamp}".format(timestamp=timestamp)) # Le timestamp avec l'heure seulement est 181434 # %% timestamp = lz.get_timestamp(timestamp_format="NOW") print("Le timestamp avec la date et l'heure sans retraitement est {timestamp}".format(timestamp=timestamp)) # Le timestamp avec la date et l'heure sans retraitement est 2020-12-09 18:14:34 # %% timestamp = lz.get_timestamp(timestamp_format="GD") print("Le timestamp avec la date sans retraitement est {timestamp}".format(timestamp=timestamp)) # Le timestamp avec la date sans retraitement est 2020-12-09 # %% timestamp = lz.get_timestamp(timestamp_format="GT") print("Le timestamp avec l'heure sans retraitement est {timestamp}".format(timestamp=timestamp)) # Le timestamp avec l'heure sans retraitement est 18:14:34
Terminal :
$ python get_timestamp.py Le timestamp sans milli secondes est 20201025_182141 Le timestamp en milli secondes est 457668 Le timestamp avec milli secondes est 20201025_182141.457668 Le timestamp avec la date seulement est 20201025 Le timestamp avec l'heure seulement est 182141 Le timestamp avec la date et l'heure sans retraitement est 2020-10-25 18:21:41 Le timestamp avec la date sans retraitement est 2020-10-25 Le timestamp avec l'heure sans retraitement est 18:21:41
-
corelibs.lazy.
get_username
()¶ Description
Récupère le nom de l’utilisateur courant- Returns
- nom de l’utilisateur courant
Exemple :
# get_username.py from corelibs import config, lazy as lz username = lz.get_username() print("Le nom de l'utilisateur actuel est \"{username}\"".format(username=username))
-
corelibs.lazy.
is_file_exists
(file_path, is_dir=False, ignore_errors=False)¶ Description
Vérifie si le fichier existe ou non- Parameters
file_path – chemin du fichier/répertoire
is_dir –
indique si la vérification porte sur un dossier ou non
valeurs possibles: False/Truevaleur par défaut: False (la vérification se fait sans distinction)ignore_errors –
forcer l’exécution lorsqu’une erreur est levée
valeurs possibles: False/Truevaleur par défaut: False (cf. DEFAULT_IGNORE_ERROR dans Installation & Mise à jour)
- Returns
- True/False
Exemple :
# is_file_exists.py # %% from corelibs import lazy as lz def test(file_test): if lz.is_file_exists(file_test): print("Le fichier \"{file_test}\" existe".format(file_test=file_test)) else: print("Le fichier \"{file_test}\" n'existe pas".format(file_test=file_test)) file = r"D:\OneDrive\Documents\_TEST_" test(file) file = r"D:\OneDrive\Documents\_TEST_\__LOGS__\Fichier.txt" test(file) # %% file = r"D:\OneDrive\Documents\_TEST_" if lz.is_file_exists(file, is_dir=True): print("Le fichier \"{file}\" existe et est un répertoire".format(file=file)) # %% file = r"D:\OneDrive\Documents\_TEST_\Fichier.txt" if lz.is_file_exists(file): print("Le fichier \"{file}\" existe".format(file=file)) # %% file = r"D:\OneDrive\Documents\_TEST_\Fichier.txt" if not lz.is_file_exists(file, is_dir=True): print("Le fichier \"{file}\" n'est pas un répertoire".format(file=file))
Terminal :
$ python get_abspath.py Le fichier "D:\OneDrive\Documents\_TEST_\__LOGS__" existe Le fichier "D:\OneDrive\Documents\_TEST_\__LOGS__\Fichier.txt" existe Le fichier "D:\OneDrive\Documents\_TEST_\__LOGS__\Fichier.txt" existe et est un répertoire Le fichier "D:\OneDrive\Documents\_TEST_\__LOGS__\Fichier.txt" existe et n'est pas un répertoire
-
corelibs.lazy.
is_interactive_python
()¶ Description
Permet de savoir si l’environnement sur lequel est exécuté le script python est un terminal Python interactive ou non (i.e. vs console ou terminal standard)- Returns
- Booléen: False/True
Exemple :
# is_interactive_python.py from corelibs import lazy as lz print(lz.is_interactive_python())
-
corelibs.lazy.
is_jupyter
()¶ Description
Permet de savoir si l’environnement sur lequel est exécuté le script python est Jupyter Notebook ou un terminal QTConsole Jupyter- Returns
- Booléen: False/True
Exemple :
# is_jupyter.py from corelibs import lazy as lz print(lz.is_jupyter())
-
corelibs.lazy.
is_namedtuple_instance
(obj)¶ Description
Permet de déterminer si l’objet passé en argument est une instance de tuple nommé.- Parameters
obj – un tuple nommé
- Returns
- Booléen: False/True
Exemple :
# is_namedtuple_instance.py from collections import namedtuple from corelibs import lazy as lz # création d'un objet PuPuce tuple nommé PuPuce = namedtuple("PuPuce", ["name", "age"]) kim = PuPuce( name="Kim", age=6 ) print(kim) # affiche bien PuPuce(name='Kim', age=6) print(lz.is_namedtuple_instance(kim)) # affiche bien True print(lz.is_namedtuple_instance("Coucou Kim")) # affiche False
-
corelibs.lazy.
is_platform
(platform_os='Windows', ignore_errors=False)¶ Description
Permet de vérifier le système d’exploitation sur lequel est lancé le script python- Parameters
platform_os –
indique quel est la plateforme de référence à vérifier .
valeurs possibles: “Windows”, “Linux” ou “OSX”valeur par défaut: “Windows”ignore_errors –
forcer l’exécution lorsqu’une erreur est levée
valeurs possibles: False/Truevaleur par défaut: False (cf. DEFAULT_IGNORE_ERROR dans Installation & Mise à jour)
- Returns
- Booléen: False/True
Exemple :
# is_platform.py from corelibs import config, lazy as lz print(lz.is_platform("Windows")) # vérfie si l'OS est Windows ou non... print(lz.is_platform("Linux")) print(lz.is_platform("OSX")) print(lz.is_platform("INCONNUE"))
-
corelibs.lazy.
is_stdin
()¶ Description
Permet de savoir si l’environnement sur lequel est exécuté le script python est un terminal standard ou non- Returns
- Booléen: False/True
-
corelibs.lazy.
is_validated_schema
(data_2_validate, schema, is_dict_schema=True, verbose=False, ignore_errors=False)¶ Description
Vérifie si une donnée est conforme au schéma descriptif. La donnée à éprouver est par défaut un dictionnaire autrement, c’est un fichier de configuration YAML.- Parameters
data_2_validate –
donnée à valider
dictionnaire ou tuple (si is_dict_schema == True)ouchemin absolu du fichier YAML à valider (si is_dict_schema == False)schema –
nom du schéma de référence
schéma (si is_dict_schema == True)ouchemin absolu du schéma YAML permettant la validation (si is_dict_schema == False)is_dict_schema –
indique si le schéma est un dictionnaire ou un fichier YAML
valeurs possibles: False/Truevaleur par défaut: Trueverbose –
afficher ou non les messages d’info/alertes
valeurs possibles: False/Truevaleur par défaut: DEFAULT_VERBOSE (cf. Installation & Mise à jour)ignore_errors –
forcer l’exécution lorsqu’une erreur est levée
valeurs possibles: False/Truevaleur par défaut: False (cf. DEFAULT_IGNORE_ERROR dans Installation & Mise à jour)
- Returns
- Booléen: False/True
Exemple :
# is_validated_schema.py # %% import schema as sc from corelibs import lazy as lz ######################################################################################################################## # TEST Schéma DICT (défaut) ######################################################################################################################## # Test schéma byte format size SCHEMA_DEFAULT_BYTE_SIZE_FORMAT = sc.Schema({ sc.Optional(sc.And(str, lambda s: s in ( # clé parmi les noms définis ci-dessous "octet", "Ko", "Mo", "Go", "To" ))): { "min_size": sc.Or(int, float) } }) # Test valide DEFAULT_BYTE_SIZE_FORMAT_OK = { "octet": {"min_size": 0}, "Ko": {"min_size": 1}, "Mo": {"min_size": 1}, "Go": {"min_size": 1}, "To": {"min_size": 0.5} } lz.is_validated_schema(DEFAULT_BYTE_SIZE_FORMAT_OK, SCHEMA_DEFAULT_BYTE_SIZE_FORMAT, verbose=True) # Test invalide DEFAULT_BYTE_SIZE_FORMAT_KO = { "octet": {"min_size": "Hello"}, "Ko": {"min_size": "Kim"}, "Mo": {"min_size": "Marie"}, "Go": {"min_size": "Adélie"}, "To": {"min_size": 7} } lz.is_validated_schema(DEFAULT_BYTE_SIZE_FORMAT_KO, SCHEMA_DEFAULT_BYTE_SIZE_FORMAT, verbose=True) # %% # Test schéma scaffolding SCHEMA_DIR_SCAFFOLDING = sc.Schema({ sc.Optional(sc.And(str, lambda s: s in ( # clé parmi les noms définis ci-dessous "input", "output", "logs", "docs" ))): { "name": sc.Regex( r"^__[a-zA-Z0-9 _-]+__$" ), "make": bool } }) # Test valide DIR_SCAFFOLDING_OK = { "input": { # dossier contenant toutes les données "entrées" "name": "__MY_INPUTS__", "make": True }, "output": { # dossier contenant toutes les données "sorties" "name": "__MY_OUTPUTS__", "make": True }, "logs": { # dossier contenant toutes les sorties "logs" "name": "__MY-LOGS__", "make": True }, } lz.is_validated_schema(DIR_SCAFFOLDING_OK, SCHEMA_DIR_SCAFFOLDING, verbose=True) # Test invalide DIR_SCAFFOLDING_KO = { "input": { # dossier contenant toutes les données "entrées" "name": "__R2 D2__", "make": False }, "output": { # dossier contenant toutes les données "sorties" "name": "__MY_OUTPUTS__", "make": "Coucou" }, "logs": { # dossier contenant toutes les sorties "logs" "name": "__MY-LOGS__", "make": True }, } lz.is_validated_schema(DIR_SCAFFOLDING_KO, SCHEMA_DIR_SCAFFOLDING) # %% # Test schéma styles des champs SCHEMA_FIELD_STYLES = sc.Schema({ sc.Optional(sc.And(str, lambda s: s in ( "asctime", "hostname", "username", "levelname", "name", "programname" ))): { "color": sc.Or(sc.And(int, lambda n: 0 <= n <= 255), sc.And(str, lambda s: s in ( "black", "blue", "cyan", "green", "magenta", "red", "white", "yellow" ))), sc.Optional(sc.And(str, sc.Use(str.lower), lambda s: s in ( "bold", "bright", "faint" ))): bool, } }) # Test valide... FIELD_STYLES_OK = { "asctime": {"color": 242, "bright": True}, "hostname": {"color": "magenta"}, "username": {"color": "yellow"}, "levelname": {"color": 242, "bright": True}, "name": {"color": "blue"}, "programname": {"color": "cyan"} } lz.is_validated_schema(FIELD_STYLES_OK, SCHEMA_FIELD_STYLES) # Test invalide... FIELD_STYLES_KO = { "asctimeZ": {"color": 242, "bright": True}, "hostname": {"color": "white"}, "username": {"color": "yellow"}, "levelname": {"color": 242, "bright": False}, "name": {"color": "blue"}, "programname": {"color": "cyan"} } lz.is_validated_schema(FIELD_STYLES_KO, SCHEMA_FIELD_STYLES) # %% # Test schéma styles des niveaux d'alertes SCHEMA_LEVEL_STYLES = sc.Schema({ sc.Optional(sc.And(str, lambda s: s in ( "critical", "error", "warning", "debug", "info", "notice", "spam", "success", "verbose" ))): { "color": sc.Or(sc.And(int, lambda n: 0 <= n <= 255), sc.And(str, lambda s: s in ( "black", "blue", "cyan", "green", "magenta", "red", "white", "yellow" ))), sc.Optional(sc.And(str, sc.Use(str.lower), lambda s: s in ( "background" ))): sc.Or(sc.And(int, lambda n: 0 <= n <= 255), sc.And(str, lambda s: s in ( "black", "blue", "cyan", "green", "magenta", "red", "white", "yellow" ))), } }) # Test valide... LEVEL_STYLES_OK = { "critical": {"color": "white", "background": "red"}, "verbose": {"color": "white"}, } lz.is_validated_schema(LEVEL_STYLES_OK, SCHEMA_LEVEL_STYLES) # Test invalide... LEVEL_STYLES_KO = { "WRONG_KEY_critical": {"color": "white", "background": "red"} } lz.is_validated_schema(LEVEL_STYLES_KO, SCHEMA_LEVEL_STYLES) # %% # Test schéma format d'affichage des logs SCHEMA_LOG_FORMAT = sc.Regex( r"^([ <>•@:=$~{}\(\)\[\]\w\d\-\.]*" + r"%\((\b(asctime|created|filename|funcName|levelname|levelno|lineno|message|module|msecs|name" + r"|pathname|process|processName|relativeCreated|thread|threadName|username|hostname)\b)\)" + r"\d*[sd]{1,1}[ <>•@:=$~{}\(\)\[\]\w\d\-\.]*)*$" ) # Test valide... LOG_FORMAT_OK = \ "> %(asctime)s %(username)s@%(hostname)s - %(name)s" \ + "[P.%(process)d - T.%(thread)d - L.%(lineno)05d] • %(levelname)13s %(message)s" lz.is_validated_schema(LOG_FORMAT_OK, SCHEMA_LOG_FORMAT) # Test invalide... LOG_FORMAT_KO = "%(asctime)s %(username)s@%(hostname)s %(name)s[%(process)d] • %(_levelname_)13s %(message)s" lz.is_validated_schema(LOG_FORMAT_KO, SCHEMA_LOG_FORMAT) # %% # Test schéma format d'affichage timestamp des logs SCHEMA_LOG_DATE_FORMAT = sc.Regex(r"^(%(%|\b[aAwdbBmyYHIpMSfzZjUWcxXGuV]\b)[ \/\-:]*)*$") # Test valide... LOG_DATE_FORMAT_OK = "%Y/%m/%d %H:%M:%S" lz.is_validated_schema(LOG_DATE_FORMAT_OK, SCHEMA_LOG_DATE_FORMAT) # Test invalide... LOG_DATE_FORMAT_KO = "%Y-%m-%d %HH : %M : %S" lz.is_validated_schema(LOG_DATE_FORMAT_KO, SCHEMA_LOG_DATE_FORMAT) # %% ######################################################################################################################## # TEST Schéma YAML ######################################################################################################################## lz.is_validated_schema( r"D:\OneDrive\Documents\[PYTHON_PROJECTS]\corelibs\tests\lazy\conf_test.yaml", r"D:\OneDrive\Documents\[PYTHON_PROJECTS]\corelibs\tests\lazy\schema_conf_test.yaml", is_dict_schema=False )
Exemple Schéma YAML :
# schema_conf_test.yaml list(include("person"), min=1) --- person: first name: str() last name: str() age: int(max=130, required=False)
Exemple fichier YAML à valider avec le schéma descriptif YAML :
- first name: "Kim Marie Adélie" last name: "TRUONG" age: 6 - first name: "Anne" last name: "TRUONG" - first name: "Michel" last name: "TRUONG" age: 231 # erreur car age supérieur à 130 qui est le maximum autorisé unknown key: "yeah!" # erreur car clé inconnue - mt: False # erreur car clé inconnu dans un nouveau bloc
Terminal :
$ python is_validated_schema.py #illustration indicative non nécessairement représentative du code en exemple
-
corelibs.lazy.
merge_dictionaries
(merged_dictionary, dictionary_2_merge)¶ Description
Permet de fusionner 2 dictionnaires ensemble/!\ ATTENTION /!\ L’ordre des dictionnaires en argument est important!- Parameters
merged_dictionary – dictionnaire conteneur destiné à recevoir le résultat de la fusion
dictionary_2_merge – dictionnaire à fusionner
- Returns
- dictionnaire résultat de la fusionouNone
Exemple :
# merge_dictionaries.py # %% from corelibs import lazy as lz # %% x = None y = {"prenom": "Kim", "age": 6} z = lz.merge_dictionaries(x, y) print(z) # {'prenom': 'Kim', 'age': 6} # %% # inversion z = lz.merge_dictionaries(y, x) print(z) # None # %% x = {"a": 1, "b": 2} y = {"b": 10, "c": 11} z = lz.merge_dictionaries(x, y) print(z) # {"a": 1, "b": 10, "c": 11} # %% x = {"b": 10, "c": 11} y = {"a": 1, "b": {"b1": "hello", "b2": 3}} z = lz.merge_dictionaries(x, y) print(z) # {"b": {"b1": "hello", "b2": 3}, "c": 11, "a": 1} # %% x = {"b": {"b1": "hello", "b2": 3}, "c": 11} y = {"a": 1, "b": {"b1": "Kim", "b2": 6}} z = lz.merge_dictionaries(x, y) print(z) # {"b": {"b1": "Kim", "b2": 6}, "c": 11, "a": 1} # %% DICT_USER = { "asctime": {"color": "BLACK"}, "levelname": {"color": "WHITE"} } DICT_REF = { "asctime": {"color": 242, "bright": True}, "hostname": {"color": "magenta"}, "username": {"color": "yellow"}, "levelname": {"color": 242, "bright": True}, "name": {"color": "blue"}, "programname": {"color": "cyan"} } MERGED_DICT = lz.merge_dictionaries(DICT_REF, DICT_USER) print(MERGED_DICT) # { # "asctime": {"color": "BLACK", "bright": True}, # "hostname": {"color": "magenta"}, # "username": {"color": "yellow"}, # "levelname": {"color": "WHITE", "bright": True}, # "name": {"color": "blue"}, # "programname": {"color": "cyan"} # }
-
corelibs.lazy.
mkdir
(location=None, make_scaffolding=True, dir_scaffolding={'docs': {'make': True, 'name': '__DOCS__'}, 'input': {'make': True, 'name': '__INPUTS__'}, 'logs': {'make': True, 'name': '__LOGS__'}, 'output': {'make': True, 'name': '__OUTPUTS__'}}, verbose=False, ignore_errors=False)¶ Description
Créer un répertoire standard ou une liste de répertoires de manière récursive ; si le ou les parents n’existent pas, ils seront créés (dans le cas d’une liste de répertoires cela permet de factoriser les instructions).- Par défaut, lorsque corelibs.lazy.mkdir() est appelé, 4 répertoires en plus sont créés :
1 pour recevoir les fichiers logs, nommé par défaut “__LOGS__”
1 pour recevoir les sorties, nommé par défaut “__OUTPUTS__”
1 pour recevoir les entrées, nommé par défaut “__INPUTS__”
1 pour recevoir les documentations et/ou spécifications, nommé par défaut “__DOCS__”
Note
- Les noms respectifs des répertoires modèles sont gérés par le dictionnaire
config.DEFAULT_DIR_SCAFFOLDING (cf. Installation & Mise à jour pour les détails.)
Il est possible de modifier les noms et/ou la création des répertoires modèles en chargeant un nouveau dictionnaire lors de l’appel de
corelibs.lazy.mkdir()
, directement en argument ou via un écrasement de la constanteDEFAULT_DIR_SCAFFOLDING
.- Parameters
location –
la location du répertoire à créer.
valeurs possibles: chemin absolu ou tuple/tableau de chemins absolusvaleur par défaut: le chemin retourné parcorelibs.lazy.get_module_path()
make_scaffolding –
indique s’il faut ou non créer les dossiers “modèle”
valeurs possibles: Dictionnairevaleur par défaut: DEFAULT_DIR_SCAFFOLDING (cf. Installation & Mise à jour)dir_scaffolding –
dictionnaire définissant les noms des dossiers “modèle” et s’il faut ou non les créer unitairement
valeurs possibles: False/Truevaleur par défaut: Trueverbose –
afficher ou non les messages d’info/alertes
valeurs possibles: False/Truevaleur par défaut: DEFAULT_VERBOSE (cf. Installation & Mise à jour)ignore_errors –
forcer l’exécution lorsqu’une erreur est levée
valeurs possibles: False/Truevaleur par défaut: False (cf. DEFAULT_IGNORE_ERROR dans Installation & Mise à jour)
- Returns
- rien…
Exemple :
# mkdir.py # %% from corelibs import lazy as lz # %% # création par défaut où se trouve l'emplacement du programme `mkdir.py` lz.mkdir() # %% # création d'un répertoire standard avec les parents si n'existe pas, sans la structure "modèle" lz.mkdir( location=r"D:\OneDrive\Documents\_TEST_\PARENTS\INEXISTANTS\DOSSIER_STANDARD", make_scaffolding=False, verbose=True ) # %% # création avec 4 dossiers par défaut de la structure "modèle" # à l'emplacement "D:\OneDrive\Documents\_TEST_\PARENTS\INEXISTANTS\DOSSIER_STANDARD" lz.mkdir(location=r"D:\OneDrive\Documents\_TEST_\PARENTS\DOSSIERS_SCAFFOLD", verbose=True) # %% # création personnalisée avec un seul dossier "__MY-LOGS__" # à l'emplacement "D:\OneDrive\Documents\_TEST_\PARENTS\INEXISTANTS\DOSSIER_STANDARD" lz.mkdir( location=r"D:\OneDrive\Documents\_TEST_\PARENTS\INEXISTANTS\DOSSIER_STANDARD", dir_scaffolding={ "input": { # dossier contenant toutes les données "entrées" "name": "__R2 D2__", "make": False }, "output": { # dossier contenant toutes les données "sorties" "name": "__MY_OUTPUTS__", "make": False }, "logs": { # dossier contenant toutes les sorties "logs" "name": "__MY-LOGS__", "make": True }, "docs": { # dossier contenant toutes les documentations/specs liées au projet "name": "__DOCS__", "make": False }, }, verbose=True ) # %% # création d'une liste de répertoires standards (sans les répertoires modèles) ayant pour structure # ...DOSSIER_T42020 # |_Dossier A # |_Dossier B # |_SDossier B1 # |_SDossier B2 lz.mkdir( location=( r"D:\OneDrive\Documents\_TEST_\DOSSIER_T42020\Dossier A", r"D:\OneDrive\Documents\_TEST_\DOSSIER_T42020\Dossier B\SDossier B1", r"D:\OneDrive\Documents\_TEST_\DOSSIER_T42020\Dossier B\SDossier B2", ), make_scaffolding=False, verbose=True ) # dans la mesure où les dossiers parents sont créés si n'existent pas, une factorisation est possible... # %% # création d'une liste de répertoires standards (avec les répertoires modèles personnalisés) ayant pour structure # ...DOSSIER_T12021 # |_Dossier A # |__MY_INPUTS__ # |__MY_OUTPUTS__ # |__MY_LOGS__ # |_Dossier B # |_SDossier B1 # |_ +3 DOSSIERS MODELES PERSONNALISÉS # |_SDossier B2 # |_ +3 DOSSIERS MODELES PERSONNALISÉS lz.mkdir( location=( r"D:\OneDrive\Documents\_TEST_\DOSSIER_T12021\Dossier A", r"D:\OneDrive\Documents\_TEST_\DOSSIER_T12021\Dossier B\SDossier B1", r"D:\OneDrive\Documents\_TEST_\DOSSIER_T12021\Dossier B\SDossier B2", ), dir_scaffolding={ "input": { # dossier contenant toutes les données "entrées" "name": "__MY_INPUTS__", "make": True }, "output": { # dossier contenant toutes les données "sorties" "name": "__MY_OUTPUTS__", "make": True }, "logs": { # dossier contenant toutes les sorties "logs" "name": "__MY_LOGS__", "make": True }, "docs": { # dossier contenant toutes les documentations/specs liées au projet "name": "__DOCS__", "make": False }, }, verbose=True ) # cette construction n'a aucun intérêt fonctionnel mais cela est possible...
Terminal :
$ python mkdir.py #illustration indicative non nécessairement représentative du code en exemple
-
corelibs.lazy.
move
(source, destination)¶ Description
Permet de déplacer un ou des fichiers vers une nouvelle destination ou des nouvelles destinations. Les fichiers sont au sens Unix du terme (i.e. soit fichier régulier, soit répertoire)- Parameters
source – indique l’emplacement source du ou des fichiers à déplacer avec le(s) chemin(s) absolu(s), avec ou sans schéma.
destination – indique l’emplacement destination du ou des fichiers à déplacer avec le(s) chemin(s) absolu(s).
- Returns
- rien…
Exemple :
# move.py # %% from corelibs import lazy as lz # %% # Création dossier destination repertoire_destination = r"D:\OneDrive\Documents\_TEST_\_NEW_DESTINATION_" lz.mkdir(repertoire_destination, make_scaffolding=False) # %% # Déplacement simple de fichier standard, sans renommage lz.move(r"\\wsl$\Ubuntu-20.04\root\.zsh_history", repertoire_destination) # chemin réseau... # %% # Déplacement simple de fichier standard, avec renommage lz.move(r"D:\OneDrive\Documents\_TEST_\_éèçàoöôîïêëùûü;.txt", repertoire_destination + "\\nouveau_nom.txt") # %% # Déplacement simple de répertoire standard, sans renommage lz.move(r"D:\OneDrive\Documents\_TEST_\__R2D2-LOGS__", repertoire_destination) # %% # Déplacement simple de répertoire standard, avec renommage lz.move(r"D:\OneDrive\Documents\_TEST_\__R2D2-LOGS__", repertoire_destination + "\\__R2D2__") # %% # Déplacement via mode modèle lz.move(r"D:\OneDrive\Documents\_TEST_\*.sas*", repertoire_destination) # modèle avec extension # ou lz.move(r"D:\OneDrive\Documents\_TEST_\*2020-11-11*", repertoire_destination) # modèle sans extension, comprenant la chaîne "2020-11-11" dans le nom # %% # Déplacement groupé dans un dossier lz.move(( r"D:\OneDrive\Documents\_TEST_\*.sas*", # avec schéma r"D:\OneDrive\Documents\_TEST_\2020-11-11.jpg", r"D:\OneDrive\Documents\_TEST_\__R2D2-LOGS__" # dossier... ), repertoire_destination) # %% # Déplacement groupé d'une liste de fichiers dans une autre liste de fichiers (fonctionnement 1-1, i.e. même nombre de fichiers en entrée et en sortie, traitée de manière itérative) lz.move(( r"D:\OneDrive\Documents\_TEST_\*.sas*", # avec schéma r"D:\OneDrive\Documents\_TEST_\2020-11-11.jpg", r"D:\OneDrive\Documents\_TEST_\__R2D2-LOGS__", # dossier... ), ( repertoire_destination, # sans renommage repertoire_destination + "\\2020-11-11_NOUVEAU_NOM.jpg", # avec renommage repertoire_destination + "\\__R2D2-NEW__", # avec renommage )) # %% ######################################################################################################################## # NOTES ################################################################################################################ # Comme sous Unix, move peut être utilisé pour renomer un fichier (chemin source = chemin cible) ######################################################################################################################## lz.move(r"D:\OneDrive\Documents\_TEST_\_éèçàoöôîïêëùûü;.txt", r"D:\OneDrive\Documents\_TEST_\NOUVEAU_NOM.txt")
-
corelibs.lazy.
open_explorer
(path)¶ Description
Permet d’ouvrir dans l’explorateur en pointant directement sur le chemin passé en argument.- Parameters
path – indique le chemin à pointer
- Returns
- rien…
Exemple :
# open_explorer.py from corelibs import lazy as lz lz.open_explorer(lz.get_home()) lz.open_explorer(r"D:\OneDrive\Documents\_TEST_") lz.open_explorer(lz.get_home() + r"\.corelibs") # ouvre le dossier contenant les données utilisateurs comme user_config.py
-
corelibs.lazy.
rename
(path, pattern, replace, transform=None, debug=True, verbose=False)¶ Description
Permet de renommer à la volée des fichiers selon des schémas regex.Note
Cette fonction est un emballage de la fonctioncorelibs.lazy.move()
. A l’utiliser de préférence si c’est un renommage simple.Warning
Compte tenu des possibles dégâts liés aux erreurs de schéma regex, par défaut, la fonction s’exécute en mode debug = TruePour que la fonction s’applique, il faut donc que le debug soit positionné à False explicitement.- Parameters
path – indique l’emplacement des fichiers sources à renommer en chemin absolu.
pattern –
indique le schéma regex des fichiers sources. Le schéma source doit contenir à minima des (), listant les différents sous groupes. Un séquençace est possible également via les directives suivantes :
%{0} pour un séquençage sans padding
%{n} où n est un entier indiquant le nombre de 0 en padding
replace – indique le schéma regex final de remplacement. Le schéma cible doit contenir à minima des \n où n est un entier représentant les sous groupes trouvés à partir du schéma source.
transform –
indique s’il y a des transformations à opérer ou non. Les transformations possibles sur le nom des fichiers cibles sont :
\U\n pour Uppercase sur le sous groupe identifié n
\L\n pour Lowercase sur le sous groupe identifié n
\C\n pour Capitalize (Premier mot en capitalizing) sur le sous groupe identifié n
\T\n pour Title (Premier Mot En Title) sur le sous groupe identifié n
\S\n pour Swapcase sur le sous groupe identifié n
debug –
indique si la fonction doit s’appliquer ou tourner à blanc
valeurs possibles: False/Truevaleur par défaut: Trueverbose –
afficher ou non les messages d’info/alertes. Dans le cadre d’une utilisation regex, le verbose peut se comporter comme un véritable spam…!!! =þ
valeurs possibles: False/Truevaleur par défaut: DEFAULT_VERBOSE (cf. Installation & Mise à jour)
- Returns
- rien…
Exemple :
# rename.py # %% from corelibs import lazy as lz # %% # Renommage simple lz.rename( path=r"D:\OneDrive\Documents\_TEST_\_TEST_RENOMMAGE_", pattern=r"_cars.sas7bdat", replace=r"nouveau_RS_cars.sas7bdat", debug=False ) # équivalent à lz.move(r"D:\OneDrive\Documents\_TEST_\_TEST_RENOMMAGE_\_cars.sas7bdat", r"D:\OneDrive\Documents\_TEST_\_TEST_RENOMMAGE_\nouveau_RS_cars.sas7bdat") # %% # Renommage simple par modèle lz.rename( r"D:\OneDrive\Documents\_TEST_\_TEST_RENOMMAGE_\__R2D2-LOGS__", r"(termcolorlog)_(\d{4})(\d{2})(\d{2})_(\d{2})(\d{2})(\d{2})(.LOG)", # Schéma source avec 8 sous groupes, (termcolorlog)_(\d{4})(\d{2})(\d{2})_(\d{2})(\d{2})(\d{2})(.LOG) r"\1_\4\3\2_\5\6.log", # Schéma cible décrivant "termcolorlog_JJMMAAAA_HHMM.log" debug=False ) # résultats : # termcolorlog_20201208_222147.LOG -> termcolorlog_08122020_2221.log # termcolorlog_20201208_222351.LOG -> termcolorlog_08122020_2223.log # termcolorlog_20201208_222452.LOG -> termcolorlog_08122020_2224.log # termcolorlog_20201208_222839.LOG -> termcolorlog_08122020_2228.log # termcolorlog_20201208_223739.LOG -> termcolorlog_08122020_2237.log # termcolorlog_20201208_223834.LOG -> termcolorlog_08122020_2238.log # termcolorlog_20201208_223920.LOG -> termcolorlog_08122020_2239.log # termcolorlog_20201208_224058.LOG -> termcolorlog_08122020_2240.log # termcolorlog_20201208_224116.LOG -> termcolorlog_08122020_2241.log # termcolorlog_20201208_224144.LOG -> termcolorlog_08122020_2241.log # %% # Renommage simple par modèle avec transformation 1er exemple lz.rename( r"D:\OneDrive\Documents\_TEST_\_TEST_RENOMMAGE_\__R2D2-LOGS__\__R2D2-LOGS__", r"(termcolorlog)_(\d{4})(\d{2})(\d{2})_(\d{2})(\d{2})(\d{2})(.LOG)", # Schéma source avec 8 sous groupes, (termcolorlog)_(\d{4})(\d{2})(\d{2})_(\d{2})(\d{2})(\d{2})(.LOG) r"\1_\4\3\2_\5\6\8", # Schéma cible décrivant "termcolorlog_JJMMAAAA_HHMM(.LOG)" transform=r"\U1\T8", # Upper sur le premier groupe et Title sur le dernier groupe debug=False ) # résultats : # termcolorlog_20201208_222147.LOG -> TERMCOLORLOG_08122020_2221.Log # termcolorlog_20201208_222351.LOG -> TERMCOLORLOG_08122020_2223.Log # termcolorlog_20201208_222452.LOG -> TERMCOLORLOG_08122020_2224.Log # termcolorlog_20201208_222839.LOG -> TERMCOLORLOG_08122020_2228.Log # termcolorlog_20201208_223739.LOG -> TERMCOLORLOG_08122020_2237.Log # termcolorlog_20201208_223834.LOG -> TERMCOLORLOG_08122020_2238.Log # termcolorlog_20201208_223920.LOG -> TERMCOLORLOG_08122020_2239.Log # termcolorlog_20201208_224058.LOG -> TERMCOLORLOG_08122020_2240.Log # termcolorlog_20201208_224116.LOG -> TERMCOLORLOG_08122020_2241.Log # termcolorlog_20201208_224144.LOG -> TERMCOLORLOG_08122020_2241.Log # %% # Renommage simple par modèle avec transformation 2ème exemple lz.rename( r"D:\OneDrive\Documents\_TEST_\_TEST_RENOMMAGE_", r"_(cars)(.*)(.sas7bdat)", # Schéma source avec 3 sous groupes r"NOUVEAU_NOM_\1_AVEC_TRANSFO\2.nouvelle_extension", # Schéma cible décrivant "NOUVEAU_NOM_(cars)_AVEC_TRANSFO(.*).nouvelle_extension" transform=r"\S1\T2", # Swapcase sur le premier groupe et Title sur le 2ème groupe debug=False ) # résultats : # _CaRS.sas7bdat -> NOUVEAU_NOM_cArs_AVEC_TRANSFO.nouvelle_extension # _cars_asia.sas7bdat -> NOUVEAU_NOM_CARS_AVEC_TRANSFO_Asia.nouvelle_extension # %% # Renommage simple par modèle avec transformation et séquences sans padding 1er exemple lz.rename( r"D:\OneDrive\Documents\_TEST_\_TEST_RENOMMAGE_\__R2D2__", r"(termcolorlog)_(\d{4})(\d{2})(\d{2})_(\d{2})(\d{2})(\d{2})(.LOG)", # Schéma source avec 8 sous groupes, (termcolorlog)_(\d{4})(\d{2})(\d{2})_(\d{2})(\d{2})(\d{2})(.LOG) r"\1_\4\3\2_%{0}_\8", # Schéma cible décrivant "TERMCOLORLOG_JJMMAAAA_%SEQUENCE_(.LOG)" transform=r"\U1\T8", # Upper sur le premier groupe et Title sur le dernier groupe debug=False, verbose=True ) # résultats : # termcolorlog_20201208_222147.LOG -> TERMCOLORLOG_08122020_1_.Log # termcolorlog_20201208_222351.LOG -> TERMCOLORLOG_08122020_2_.Log # termcolorlog_20201208_222452.LOG -> TERMCOLORLOG_08122020_3_.Log # termcolorlog_20201208_222839.LOG -> TERMCOLORLOG_08122020_4_.Log # termcolorlog_20201208_223739.LOG -> TERMCOLORLOG_08122020_5_.Log # termcolorlog_20201208_223834.LOG -> TERMCOLORLOG_08122020_6_.Log # termcolorlog_20201208_223920.LOG -> TERMCOLORLOG_08122020_7_.Log # termcolorlog_20201208_224058.LOG -> TERMCOLORLOG_08122020_8_.Log # termcolorlog_20201208_224116.LOG -> TERMCOLORLOG_08122020_9_.Log # termcolorlog_20201208_224144.LOG -> TERMCOLORLOG_08122020_10_.Log # %% # Renommage simple par modèle avec transformation et séquences avec padding 2ème exemple lz.rename( r"D:\OneDrive\Documents\_TEST_\_TEST_RENOMMAGE_\__R2D2__\__R2D2-LOGS__", r"(termcolorlog)_(\d{4})(\d{2})(\d{2})_(\d{2})(\d{2})(\d{2})(.LOG)", # Schéma source avec 8 sous groupes, (termcolorlog)_(\d{4})(\d{2})(\d{2})_(\d{2})(\d{2})(\d{2})(.LOG) r"_%{10}_\1_\4\3\2_%{0}_\8", # Schéma cible décrivant "_%SEQUENCE_PADDING10_TERMCOLORLOG_JJMMAAAA_%SEQUENCE_PADDING_(.LOG)" transform=r"\U1\T8", # Upper sur le premier groupe et Title sur le dernier groupe debug=False ) # résultats : # termcolorlog_20201208_182147.LOG -> _0000000001_TERMCOLORLOG_08122020_0000000001_.Log # termcolorlog_20201208_182351.LOG -> _0000000002_TERMCOLORLOG_08122020_0000000002_.Log # termcolorlog_20201208_182452.LOG -> _0000000003_TERMCOLORLOG_08122020_0000000003_.Log # termcolorlog_20201208_182839.LOG -> _0000000004_TERMCOLORLOG_08122020_0000000004_.Log # termcolorlog_20201208_183739.LOG -> _0000000005_TERMCOLORLOG_08122020_0000000005_.Log # termcolorlog_20201208_183834.LOG -> _0000000006_TERMCOLORLOG_08122020_0000000006_.Log # termcolorlog_20201208_183920.LOG -> _0000000007_TERMCOLORLOG_08122020_0000000007_.Log # termcolorlog_20201208_184058.LOG -> _0000000008_TERMCOLORLOG_08122020_0000000008_.Log # termcolorlog_20201208_184116.LOG -> _0000000009_TERMCOLORLOG_08122020_0000000009_.Log # termcolorlog_20201208_184144.LOG -> _0000000010_TERMCOLORLOG_08122020_0000000010_.Log
-
corelibs.lazy.
reverse_named_tuple
(named_tuple, convert_2_dict=False, ignore_errors=False)¶ Description
Permet d’inverser l’ordre d’un tuple nommé.- Parameters
named_tuple – indique le tuple nommé à inverser
convert_2_dict –
indique s’il faut convertir ou non le tuple nommé en dictionnaire
valeurs possibles: False/Truevaleur par défaut: Falseignore_errors –
forcer l’exécution lorsqu’une erreur est levée
valeurs possibles: False/Truevaleur par défaut: False (cf. DEFAULT_IGNORE_ERROR dans Installation & Mise à jour)
- Returns
- tuple nommé avec le nom de classe et attributs tels que passés en argumentoudictionnaire (conversion du tuple nommé)
Exemple :
# reverse_named_tuple.py # %% from corelibs import lazy as lz # %% # création d'un tuple nommé byte_size = lz.get_bytes_size_formats(1739886085) print(byte_size) # ByteSize(byte=1739886085, kilobyte=1699107.5, megabyte=1659.28, gigabyte=1.62, terabyte=0.0) # %% # renverser le tuple nommé reverse_nt = lz.reverse_named_tuple(byte_size) print(reverse_nt) # ByteSize(terabyte=0.0, gigabyte=1.62, megabyte=1659.28, kilobyte=1699107.5, byte=1739886085.0) # %% # comme la classe originale existe lors de l'inversion, il est toujours possible d'accéder à un des attributs print(reverse_nt.megabyte) # affichera 1659.28 # %% # renverser le tuple nommé avec conversion en dictionnaire reverse_nt = lz.reverse_named_tuple(byte_size, convert_2_dict=True) print(reverse_nt) # {'terabyte': 0.0, 'gigabyte': 1.62, 'megabyte': 1659.28, 'kilobyte': 1699107.5, 'byte': 1739886085} # %% # exemple avec dir_n_basename() dir_n_basename = lz.get_dir_n_basename(r"C:\Users\M47624\corelibs\tests\lazy\get_dir_n_basename.py") print(dir_n_basename) # DirPathnBaseName(dir_path='C:\\Users\\M47624\\corelibs\\tests\\lazy', base_name='get_dir_n_basename.py') # %% print(lz.reverse_named_tuple(dir_n_basename)) # DirPathnBaseName(base_name='get_dir_n_basename.py', dir_path='C:\\Users\\M47624\\corelibs\\tests\\lazy') # %% print(dir_n_basename.base_name) # get_dir_n_basename.py
Module cleanse¶
Description générale
Module pour purifier/nettoyer les données
-
corelibs.cleanse.
cleanse_file
(file_path, strip_non_breaking_space=True, out_file_path=None, cleansed_suffix='_CLEANSED', time_stamp='DT', encoding='Latin-1', ignore_errors=False)¶ Description
Permet de purifier le fichier des caractères non imprimables, ainsi que les espaces insécables pouvant générer des erreurs lors des imports- Parameters
file_path – indique le fichier en entrée avec son chemin absolu
strip_non_breaking_space –
indique la suppression des espaces insécables
valeurs possibles: False/Truevaleur par défaut: Trueout_file_path – indique le fichier en sortie avec son chemin absolu
cleansed_suffix – indique le suffix à utiliser dans le nom de sortie (si out_file_path == None)
time_stamp –
indique le timestamp à appliquer dans le nom de sortie (si out_file_path == None)
valeurs possibles: DT, D, T ou Nonevaleur par défaut: DTencoding – indique l’encodage à la lecture/écriture
ignore_errors –
forcer l’exécution lorsqu’une erreur est levée
valeurs possibles: False/Truevaleur par défaut: False (cf. DEFAULT_IGNORE_ERROR dans Installation & Mise à jour)
- Returns
- rien…
Exemple :
# cleanse_file.py # %% from corelibs import cleanse as cls, log # %% # nettoyage fichier des caractères non imprimables @log.timing() @log.status_bar() def stress_test(): cls.cleanse_file( r"D:\OneDrive\Documents\_TEST_\StockEtablissement_utf8_A3T.csv", time_stamp="D", strip_non_breaking_space=True ) stress_test() # non printable seul : # Durée exécution : 00:01:36.11 pour 30 millions de lignes # Durée exécution : 00:04:48.07 pour 90 millions de lignes # non printable + non breaking space # Durée exécution : 00:02:25.80 pour 30 millions de lignes # Durée exécution : 00:07:11.64 pour 90 millions de lignes
-
corelibs.cleanse.
is_datetime
(dt_str, in_format='%d/%m/%Y %H:%M:%S', out_format='%d/%m/%Y %H:%M:%S', in_locale_time='fr', out_locale_time='fr', ignore_errors=False, check_only=False)¶ Description
Vérifie si une chaîne est un datetime ou non.Permet également de convertir le datetime vers un format souhaité (cf. Liste des codes pour le formatage des timestamps pour les formats)- Parameters
dt_str – indique la variable horodatée (datetime ou string)
in_format – indique le format d’entrée (n’est pas nécessaire si le dt_str est une instance de datetime)
out_format – indique le format sortie
in_locale_time – indique la langue de la date en entrée (cf. DEFAULT_LOCALE_TIME dans Installation & Mise à jour). Si chaîne vide, alors la langue utilisée sera celle définie par le système d’exploitation sur lequel est exécutée
corelibs.cleanse.is_datetime()
out_locale_time – indique la langue de la date en sortie (cf. DEFAULT_LOCALE_TIME dans Installation & Mise à jour). Si chaîne vide, alors la langue utilisée sera celle définie par le système d’exploitation sur lequel est exécutée
corelibs.cleanse.is_datetime()
ignore_errors –
forcer l’exécution lorsqu’une erreur est levée
valeurs possibles: False/Truevaleur par défaut: False (cf. DEFAULT_IGNORE_ERROR dans Installation & Mise à jour)check_only –
permet de retourner un booléen au lieu de la chaîne de caractères transformée (utile dans le cas où il est seulement souhaité un contrôle, sans nécessairement une transformation pour éventuellement y appliquer une règle de gestion propre)
valeurs possibles: False/Truevaleur par défaut: False
- Returns
- booléen: False/True si check_only == True (comportement par défaut)ouchaine vide (si forcé)ouNone (si forcé lorsque dt_str est une instance de datetime)ou:magenta:(str)`datetime` au format défini via out_format
Exemple :
# is_datetime.py # %% import datetime as dt from corelibs import cleanse as cls # %% # forcer le traitement des instructions suivantes même en erreur... print(cls.is_datetime("Hello Kim", ignore_errors=True)) # retourne vide... # %% # Datetime en chaine de caractère # forcer le retour à vide (utile pour les données loufoques de la morkitu) print(cls.is_datetime("2020-08-31", "%Y-%m-%d", out_format="")) # retourne vide... # %% print(cls.is_datetime("2020-08-31", "%Y-%m-%d")) # retourne 31/08/2020 00:00:00 print(cls.is_datetime("lun., 31 août 2020 15:57:43", "%a, %d %b %Y %H:%M:%S")) # 31/08/2020 15:57:43 # %% # format entrée en anglais, avec une sortie française (par défaut)... print(cls.is_datetime("Mon, 31 Aug 2020 15:57:43", in_format="%a, %d %b %Y %H:%M:%S", out_format="le %A %d %b %Y à %H h et %M min", in_locale_time="en")) # le lundi 31 août 2020 à 15 h et 57 min # %% # format entrée en anglais, avec une sortie suédoise... print(cls.is_datetime("Mon, 30 Oct 2020 15:57:43", in_format="%a, %d %b %Y %H:%M:%S", out_format="%A %d %b %Y • %H:%M:%S", in_locale_time="en", out_locale_time="sv")) # fredag 30 okt 2020 • 15:57:43 # %% # format entrée en français (par défaut), avec une sortie anglaise... print(cls.is_datetime("lun., 31 août 2020 15:57:43", in_format="%a, %d %b %Y %H:%M:%S", out_format="%A %d %b %Y @ %HH n %Mmin", out_locale_time="en")) # Monday 31 Aug 2020 @ 15H n 57min # %% # Instance datetime _now = dt.datetime.now() # sortie par défaut quand c'est une date... print(cls.is_datetime(_now)) # retourne 15/12/2020 23:58:08 # %% # sortie avec conversion format print(cls.is_datetime(_now, out_format="le %A %d %b %Y à %H h et %M min")) # le mardi 15 déc. 2020 à 23 h et 58 min
-
corelibs.cleanse.
is_email
(email, check_only=True, check_deliverability=False, normalize=True, correction=True, new_email='', extraction=False, smtp_utf8=False)¶ Description
Permet de valider et d’uniformiser un email- Parameters
email – email à traiter
check_only –
permet de retourner un booléen au lieu de l’email normalisé
valeurs possibles: False/Truevaleur par défaut: Truecheck_deliverability –
indique s’il faut vérifier la délivrabilité de l’email (si son format est valide).
valeurs possibles: False/Truevaleur par défaut: Falsenormalize –
indique s’il faut normaliser l’email en sortie
valeurs possibles: False/Truevaleur par défaut: Truecorrection – indique s’il faut corriger l’email faut avec la valeur passée via new_email
new_email –
indique la chaîne de remplacement si l’email est faux
valeurs possibles: chaine de caractèresvaleur par défaut: chaine videextraction –
indique s’il faut extraire l’email passé en argument
valeurs possibles: False/Truevaleur par défaut: Falsesmtp_utf8 –
indique si l’email passé en argument est encodé en utf8
valeurs possibles: False/Truevaleur par défaut: False
- Returns
- booléen: False/True si check_only == True (comportement par défaut)ouemail normalisé avec un encodage ASCII ou en UTF8 (si smtp_utf8 == True)outuple nommé avec comme attributs :
email (email complet normalisé en UTF8)
local_part (préfixe du @ en UTF8)
domain (suffixe du @ en UTF8)
ascii_email (email complet normalisé en ASCII)
ascii_local_part (préfixe du @ en ASCII ou None si smtp_utf8 == True)
ascii_domain (suffixe du @ en ASCII ou Punnycode si smtp_utf8 == True)
smtp_utf8
mx (entrée MX du/des serveurs DNS)
mx_fallback_type (None si tout est OK, sinon les possibles erreurs levées)
Exemple :
# is_email.py # %% from corelibs import cleanse as cls, log, config config.DEFAULT_LOG_LEVEL = 10 @log.dict_dumping def dump(tuple_2_dump): return tuple_2_dump # vérification par défaut print(cls.is_email("prenom.nom@BPIfrance.fr")) # affichera True car correctement formaté # vérification avec l'option déliverabilité avec une erreur typo dans le nom de domaine print(cls.is_email("prenom.nom@bpi_france.fr", check_deliverability=True)) # affichera False car le nom de domaine bpi_france.fr n'existe pas # vérification avec normalisation print(cls.is_email("prenom.nom@BPIfrance.fr", check_only=False)) # affichera prenom.nom@bpifrance.fr # vérification avec extraction des méta données res = cls.is_email("prenom.nom@BPIfrance.fr", check_only=False, extraction=True, check_deliverability=True) print(res) # affichera l'objet # Email( # email='prenom.nom@bpifrance.fr', # local_part='prenom.nom', # domain='bpifrance.fr', # ascii_email='prenom.nom@bpifrance.fr', # ascii_local_part='prenom.nom', # ascii_domain='bpifrance.fr', # smtp_utf8=False, # mx=[ # (5, 'mail1.bpifrance.fr'), # (5, 'mail2.bpifrance.fr'), # (10, 'mail1.oseo.fr'), # (10, 'mail2.oseo.fr'), # (15, 'mail0.bpifrance.fr'), # (15, 'mail3.bpifrance.fr')], # mx_fallback_type=None # ) dump(res) # affichage plus lisible pour notre regard, au format YAML (mode DEBUG seulement) # %% # vérification avec un encodage utf8 print(cls.is_email("おはよう@例え.テスト", check_only=False, smtp_utf8=True)) # affichera おはよう@例え.テスト <=> bonjour@parexemple.test # extraction utf8 res = cls.is_email("おはよう@例え.テスト", check_only=False, extraction=True, smtp_utf8=True) print(res) # affichera l'objet # Email( # email='おはよう@例え.テスト', # local_part='おはよう', # domain='例え.テスト', # ascii_email=None, # ascii_local_part=None, # ascii_domain='xn--r8jz45g.xn--zckzah', # domaine ASCII encodé avec sa version Punycode (cf. https://www.rfc-editor.org/rfc/rfc3492.txt) # smtp_utf8=True, # mx=None, # mx_fallback_type=None # ) dump(res) # affichage plus lisible pour notre regard, au format YAML (mode DEBUG seulement)
-
corelibs.cleanse.
is_phone_number
(phone_number, check_only=True, normalize=True, country_code='FR', phone_number_format=1, correction=True, new_phone='', extraction=False)¶ Description
Permet de qualifier un n° de téléphone au format international, national ou E164- Parameters
phone_number – n° de téléphone à traiter
check_only –
permet de retourner un booléen au lieu du n° de téléphone normalisé
valeurs possibles: False/Truevaleur par défaut: Truenormalize –
indique s’il faut normaliser le n° de téléphone
valeurs possibles: False/Truevaleur par défaut: Truecountry_code –
indique le code du pays (code ISO sur 2 caractères)
valeurs possibles: Code ISO pays ou None (si None alors le n° de téléphone doit être au format international, +XX??????????)valeur par défaut: FRphone_number_format –
indique le format de sortie
valeurs possibles: config.PHONE_NUMBER_FORMAT_INTERNATIONAL, config.PHONE_NUMBER_FORMAT_NATIONAL ou config.PHONE_NUMBER_FORMAT_E164valeur par défaut: config.PHONE_NUMBER_FORMAT_INTERNATIONALcorrection –
indique s’il faut nettoyer/consolider le n° de téléphone
valeurs possibles: False/Truevaleur par défaut: Truenew_phone –
indique la chaîne de remplacement si le n° de téléphone est faux
valeurs possibles: chaine de caractèresvaleur par défaut: chaine videextraction –
indique s’il faut extraire le n° passé en argument via phone_number
valeurs possibles: False/Truevaleur par défaut: False
- Returns
- booléen: False/True si check_only == True (comportement par défaut)oun° de téléphone normalisé au format phone_number_format et consolidé si correction == Trueoutuple nommé avec comme attributs :
country_code
phone_number
national_number (présent ici seulement par commodité)
international_number (présent ici seulement par commodité)
e164_number (présent ici seulement par commodité)
given_number
Exemple :
# is_phone_number.py # %% from corelibs import cleanse as cls, log, config config.DEFAULT_LOG_LEVEL = 10 # %% # qualification par défaut, en n° français liste_nationale = ( "06 89 97.21-31", # OK "06 89.97.21-32", # OK "01.89.97.21.32", # OK "01.89.97.21.320", # KO ) res = [] for n in liste_nationale: res.append(cls.is_phone_number(n)) print(res) # affichera [True, True, True, False] # %% # qualifacation avec des n° au format international liste_internationale = ( "+3306 89 97.21-31", # français OK "+3306 89 97.21-31 0", # français KO "+4412 89.97.21-3------------------2", # anglais OK "+4412 89.97.21-3------------------2 0", # anglais KO "+1510 - 748 - 8230", # américain OK "+1510 - 748 - 8230 - 0", # américain KO ) res = [] for n in liste_internationale: res.append(cls.is_phone_number(n)) print(res) # affichera [True, False, True, False, True, False] # %% # normalisation et correction des n° de téléphone res = [] for n in liste_internationale: res.append(cls.is_phone_number(n, check_only=False)) print(res) # affichera ['+33 6 89 97 21 31', '', '+44 1289 972132', '', '+1 510-748-8230', ''] # %% # extraction des n° de téléphone def _(): res = [] for phone_number in liste_internationale: res.append(cls.is_phone_number(phone_number, check_only=False, extraction=True)) return res phones_number = _() print(phones_number) # affichera # [ # PhoneNumber(country_code=33, phone_number=689972131, national_number='06 89 97 21 31', international_number='+33 6 89 97 21 31', e164_number='+33689972131', given_number='+3306 89 97.21-31'), # PhoneNumber(country_code='', phone_number='', national_number='', international_number='', e164_number='', given_number='+3306 89 97.21-31 0'), # PhoneNumber(country_code=44, phone_number=1289972132, national_number='01289 972132', international_number='+44 1289 972132', e164_number='+441289972132', given_number='+4412 89.97.21-3------------------2'), # PhoneNumber(country_code='', phone_number='', national_number='', international_number='', e164_number='', given_number='+4412 89.97.21-3------------------2 0'), # PhoneNumber(country_code=1, phone_number=5107488230, national_number='(510) 748-8230', international_number='+1 510-748-8230', e164_number='+15107488230', given_number='+1510 - 748 - 8230'), # PhoneNumber(country_code='', phone_number='', national_number='', international_number='', e164_number='', given_number='+1510 - 748 - 8230 - 0') # ] # %% # dumping pour une meilleure visualisation @log.dict_dumping def dump(tuple_2_dump): return tuple_2_dump for phone in phones_number: dump(phone) # affichage plus lisible pour notre regard, au format YAML (mode DEBUG seulement)
-
corelibs.cleanse.
is_schema
(string, schema, regex_flag=re.IGNORECASE)¶ Description
Permet de qualifier une chaîne de caractères par rapport à un schéma regex- Parameters
string – chaine de caractères à qualifier
schema – schéma regex
regex_flag –
indique le flag regex à utiliser. cf. Liens utiles, Librairie regex pour plus de détails
valeurs possibles: None ou constante regex (séparée par | si plusieurs constantes, par exemple re.M | re.I)valeur par défaut: re.IGNORECASE
- Returns
- booléen: False/True
Exemple :
# is_schema.py # %% from corelibs import cleanse as cls chaine = """ Somewhere, something incredible is waiting to be known. For small creatures such as we the vastness is bearable only through love. We're made of star stuff. We are a way for the cosmos to know itself. If you want to make an apple pie from scratch, you must first create the universe. Science is a way of thinking much more than it is a body of knowledge. Imagination will often carry us to worlds that never were. But without it we go nowhere. Every one of us is, in the cosmic perspective, precious. If a human disagrees with you, let him live. In a hundred billion galaxies, you will not find another. Science is not only compatible with spirituality; it is a profound source of spirituality. Absence of evidence is not evidence of absence. We live in a society exquisitely dependent on science and technology, in which hardly anyone knows anything about science and technology. === Quelque part, quelque chose d'incroyable attend d'être connu. Pour les petites créatures comme nous, l'immensité n'est supportable que par l'amour. Nous sommes faits de poussières d'étoiles. Nous sommes un moyen pour le cosmos de se connaître. Si vous voulez faire une tarte aux pommes à partir de rien, vous devez d'abord créer l'univers. La science est une façon de penser bien plus qu’un ensemble de connaissances. L'imagination nous transportera souvent dans des mondes qui ne l'ont jamais été. Mais sans elle, nous allons nulle part. Chacun de nous est, dans la perspective cosmique, précieux. Si une personne n'est pas d'accord avec vous, laissez la vivre. Dans un rayon de cent milliards de galaxies, vous n'en trouverez pas d'autres. La science n'est pas seulement compatible avec la spiritualité; c'est une source profonde de spiritualité. L'absence de preuve n'est pas une preuve d'absence. Nous vivons dans une société extrêmement dépendante de la science et de la technologie, dans laquelle presque personne ne sait rien de la science et de la technologie. Carl SAGAN """ # recherche début de chaîne... print(cls.is_schema(chaine, schema=r"^somewhere.*", regex_flag=None)) # affichera False car Somewhere ne commence qu'à la 2ème ligne # recherche du mot somewhere sans distinction print(cls.is_schema(chaine, schema=r"somewhere")) # affichera True # recherche début de chaîne en "cassant" la chaîne principale for s in chaine.split("\n"): if cls.is_schema(s, schema=r"^somewhere.*"): print(s) # affichera Somewhere, something incredible is waiting to be known. # recherche si signé par Carl SAGAN print(cls.is_schema(chaine, schema=r"Carl SAGAN$")) # affichera True # %% # Exemple plus concrète et sérieuse =þ # validation d'un format de fichier avec ID, Prénom et Date anniversaire sous la forme JJ/MM/AAAA, séparé par des ; # ce format est traduit par le schéma suivant ^[0-9]{2};\w+;([0-9]{2}\/){2}[0-9]{4} chaine = """ ID;Prénom;Date Anniversaire 01;Kim;28/11/2013 02,Mickey,18/11/1928 XX;YODA;1980 """ _chaine = chaine.split("\n") res = _chaine[0:2] for s in _chaine[2:-1]: if cls.is_schema(s, r"^[0-9]{2};\w+;([0-9]{2}\/){2}[0-9]{4}"): res.append(s + "OK".rjust(31 - len(s))) else: res.append(s + "KO".rjust(31 - len(s))) res.append("".join(_chaine[-1:])) # inutile mais pour être rigoureux, il y a la dernière chaine à blanc qui doit être prise en compte... print("\n".join(res)) # ce qui affichera, avec la 2ème ligne validée et les autres lignes non validées # ID;Prénom;Date Anniversaire # 01;Kim;28/11/2013 OK # 02,Mickey,18/11/1928 KO # XX;YODA;1980 KO
-
corelibs.cleanse.
is_siren
(siren, check_only=True, correction=True, new_siren='')¶ Description
Vérifie si un siren est correctement formaté et est valide au sens technique du terme (cf. alogrithme de Luhn)- Parameters
siren – chaine de caractères ou liste de chaînes de caractères à traiter
check_only –
permet de retourner un booléen au lieu du siren corrigé (si en erreur) ou consolidé (si il manque des caractères 0 devant pour former un siren à 9 caractères)
valeurs possibles: False/Truevaleur par défaut: Truecorrection –
indique s’il faut nettoyer/consolider le siren
valeurs possibles: False/Truevaleur par défaut: Truenew_siren –
indique la chaîne de remplacement si le siren est faux
valeurs possibles: chaine de caractèresvaleur par défaut: chaine vide
- Returns
- booléen: False/True si check_only == True (comportement par défaut)ousiren/liste de siren corrigé/consolidé (si correction == True)
Exemple :
# is_siren.py # %% from corelibs import cleanse as cls # vérification sur 1 siren correctement formaté res = cls.is_siren("325175") print(res) # affichera un booléen, ici True # vérication sur le même siren avec un retour en chaîne de cractères res = cls.is_siren("325175", check_only=False) print(res) # affichera "000325175" qui est la version consolidée, avec le bon formatage pour respecter le format du siren sur 9 caractères # vérification sur une liste de sirens sirens = ( "732829320", # siren sur 9 OK "303663981", # siren sur 9 KO "60801487", # siren sur 8 OK "5450093", # siren sur 7 OK "325175", # siren sur 6 OK ) print(cls.is_siren(sirens)) # affichera [True, False, True, True, True] print(cls.is_siren(sirens, check_only=False)) # affichera la version corrigée ['732829320', '', '060801487', '005450093', '000325175'] <= le 2ème siren qui est faux est par défaut remplacé par une chaîne vide print(cls.is_siren(sirens, check_only=False, new_siren="999999999")) # affichera ['732829320', '999999999', '060801487', '005450093', '000325175'], au lieu de ['732829320', '', '060801487', '005450093', '000325175'] qui est le comportement par défaut
-
corelibs.cleanse.
is_siret
(siret, check_only=True, correction=True, new_siret='', extraction=False)¶ Description
Vérifie si un siret est correctement formaté et est valide au sens technique du terme (cf. alogrithme de Luhn) - prend également en compte les établissements particuliers de La Poste ayant pour sirène 356000000- Parameters
siret – chaine de caractères ou liste de chaînes de caractères à traiter
check_only –
permet de retourner un booléen au lieu du siret corrigé (si en erreur) ou consolidé (si il manque des caractères 0 devant pour former un siret à 15 caractères)
valeurs possibles: False/Truevaleur par défaut: Truecorrection –
indique s’il faut nettoyer/consolider le siret
valeurs possibles: False/Truevaleur par défaut: Truenew_siret –
indique la chaîne de remplacement si le siret est faux
valeurs possibles: chaine de caractèresvaleur par défaut: chaine videextraction –
indique s’il faut extraire le siren/nic du siret
valeurs possibles: False/Truevaleur par défaut: False
- Returns
- booléen: False/True si check_only == True (comportement par défaut)ousiret/liste de siret corrigé/consolidé (si correction == True)outuple nommé avec comme attributs :
siren
nic
siret (présent ici seulement par commodité)
Exemple :
# is_siret.py # %% from corelibs import cleanse as cls # vérification sur 1 siret correctement formaté res = cls.is_siret(("33243395200022")) print(res) # affichera un booléen, ici True # vérication sur le même siret avec un retour en chaîne de cractères res = cls.is_siret("33243395200022", check_only=False) print(res) # affichera 33243395200022 # extraction du même siret validé res = cls.is_siret("33243395200022", check_only=False, extraction=True) print(res) # affichera Siret(siren='332433952', nic='00022', siret='33243395200022') print(f"Le siret {res.siret} est composé du siren {res.siren} et du nic {res.nic}") # affichera Le siret 33243395200022 est composé du siren 332433952 et du nic 00022 # vérification sur une liste de sirets sirets = ( "33243395200022", # siret sur 14 OK "33243395200021", # siret sur 14 KO "00032517500057", # siret sur 14 OK "32517500024", # siret sur 11 OK "32517501024", # siret sur 11 KO "35600000049837", # cas particulier La Poste "35600000052135", # cas particulier La Poste ) print(cls.is_siret(sirets)) # affichera [True, False, True, True, False, True, True] print(cls.is_siret(sirets, check_only=False)) # affichera la version corrigée ['33243395200022', '', '00032517500057', '00032517500024', '', '35600000049837', '35600000052135'] print(cls.is_siret(sirets, check_only=False, new_siret="99999999999999")) # affichera ['33243395200022', '99999999999999', '00032517500057', '00032517500024', '99999999999999', '35600000049837', '35600000052135'] # extractions sur la même liste avec une annotation quand le siren est celui de La Poste is_laposte = lambda _: "(Établissement La Poste)" if _ == "356000000" else "" for s in cls.is_siret(sirets, check_only=False, new_siret="---------------", extraction=True): print(f"Le siret {s.siret} est composé du siren {s.siren} et du nic {s.nic} {is_laposte(s.siren)}") # affichera # Le siret 33243395200022 est composé du siren 332433952 et du nic 00022 # Le siret --------------- est composé du siren --------- et du nic ----- # Le siret 00032517500057 est composé du siren 000325175 et du nic 00057 # Le siret 00032517500024 est composé du siren 000325175 et du nic 00024 # Le siret --------------- est composé du siren --------- et du nic ----- # Le siret 35600000049837 est composé du siren 356000000 et du nic 49837 (Établissement La Poste) # Le siret 35600000052135 est composé du siren 356000000 et du nic 52135 (Établissement La Poste)
-
corelibs.cleanse.
is_str
(string, strip_non_printable_char=True, strip_accented_char=False, strip_num_char=False, chars_2_replace=None, replaced_chars=None, unicode_categories_2_remove=None, check_only=False)¶ Description
Vérifie si une chaîne de caractères est bien une chaine de caractères.Permet également de faire du nettoyage de caractères- Parameters
string – chaine de caractères à traiter
strip_non_printable_char –
permet de nettoyer la chaine de tous les caractères de contrôles parasites.
valeurs possibles: False/Truevaleur par défaut: Truestrip_accented_char –
permet de nettoyer la chaine de tous les caractères accentués, avec leurs équivaleuts sans accent.
valeurs possibles: False/Truevaleur par défaut: Falsestrip_num_char –
permet de nettoyer la chaine de tous les caractères numériques parasites (avec ou non des caractères séparateurs, ainsi que les signes et/ou opérateur comme le “-” ou “:”)
valeurs possibles: False/Truevaleur par défaut: Falsechars_2_replace –
permet de faire du remplacement de caractères unitairement.
valeurs possibles: Chaine de caractère ou Dictionnaire associatif (si Dictionnaire, alors l’argument replaced_chars est optionnel, cf. exemple)replaced_chars – indique la liste des caractères de remplacement, si cet argument est renseigné, doit fonctionner conjointement avec l’argument chars_2_replace (cf. exemple)
unicode_categories_2_remove –
permet de spécifier une classe de caractères Unicode à supprimer. Cet argument est optionnel et doit être utilisé avec l’argument strip_non_printable_char
valeurs possibles: Liste ou Tuple de classe Unicode (cf. Classification des caractères Unicodes pour plus de détails sur les classifications des caractères Unicodes)valeur par défaut: Nonecheck_only –
permet de retourner un booléen au lieu de la chaîne de caractères transformée (utile dans le cas où il est seulement souhaité un contrôle, sans nécessairement une transformation pour éventuellement y appliquer une règle de gestion propre)
valeurs possibles: False/Truevaleurs par défaut: False
- Returns
- chaine de caractères transformée si check_only == False (comportement par défaut)sinon True/False
Note
si chars_2_replace est un dictionnaire alors il est possible de remplacer plusieurs caractères d’un seul tenant {“ABC”: “Nouvelle chaines de caractères”} - ou la suite “ABC” sera remplacée par “Nouvelle chaines de caractères” (cf. exemple ci-dessous)Exemple :
# is_str.py # %% from corelibs import cleanse as cls # test si chaine caractères print(cls.is_str(123)) # affichera une chaîne vide "" # suppression de tous les caractères non imprimables # \x00 <=> NULL (NUL) # \x01 <=> START OF HEADING (SOH) # \x02 <=> START OF TEXT (STX) # \x03 <=> END OF TEXT (ETX) # \x04 <=> END OF TRANSMISSION (EOT) # \x05 <=> END OF QUERY (ENQ) # \x06 <=> ACKNOWLEDGE (ACK) # \x07 <=> BEEP (BEL) # \x08 <=> BACKSPACE (BS) # \x09 <=> HORIZONTAL TAB (HT) # \x0A <=> LINE FEED (LF) # \x0B <=> VERTICAL TAB (VT) # \x0C <=> FF (FORM FEED) # \x0D <=> CR (CARRIAGE RETURN) # \x0E <=> SO (SHIFT OUT) # \x0F <=> SI (SHIFT IN) # \x10 <=> DATA LINK ESCAPE (DLE) # \x11 <=> DEVICE CONTROL 1 (DC1) # \x12 <=> DEVICE CONTROL 2 (DC2) # \x13 <=> DEVICE CONTROL 3 (DC3) # \x14 <=> DEVICE CONTROL 4 (DC4) # \x15 <=> NEGATIVE ACKNOWLEDGEMENT (NAK) # \x16 <=> SYNCHRONIZE (SYN) # \x17 <=> END OF TRANSMISSION BLOCK (ETB) # \x18 <=> CANCEL (CAN) # \x19 <=> END OF MEDIUM (EM) # \x1A <=> SUBSTITUTE (SUB) # \x1B <=> ESCAPE (ESC) # \x1C <=> FILE SEPARATOR (FS) RIGHT ARROW # \x1D <=> GROUP SEPARATOR (GS) LEFT ARROW # \x1E <=> RECORD SEPARATOR (RS) UP ARROW # \x1F <=> UNIT SEPARATOR (US) DOWN ARROW chaine = """ \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19 \x1A\x1B\x1C\x1D\x1E\x1F Hello, je suis la chaîne qui ne sera pas nettoyée... \x12\x13\x14\x15\x16\x17\x18 ❤ =} """ print(cls.is_str(chaine)) # affiche " Hello, je suis la chaîne qui ne sera pas nettoyée... ❤ =}" # %% # Supression via des classes de caractères Unicode # Cc => Caractères de contrôles (non imprimables) # Lu => Caractères majuscules # Zs => espace print(cls.is_str(chaine, unicode_categories_2_remove=("Cc", "Lu", "Zs"))) # affiche "ello,jesuislachaînequineserapasnettoyée...❤=}" # %% # suppression des caractères accentués en les ramplaçant par leurs équivalents non accentués chaine = "Hello, voici ma liste de caractères accentués ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿŒœŠšŸƒ" print(cls.is_str(chaine, strip_accented_char=True)) # affiche "Hello, voici ma liste de caracteres accentues AAAAAAÆCEEEEIIIIÐNOOOOOØUUUUYÞßaaaaaaæceeeeiiiiðnoooooøuuuuyþyŒœSsYƒ" # %% # suppression des caractères numériques avec les signes, opérateurs et séparateurs chaine = "Hello, voici ma liste avec des caractères numériques : date(28/11/2013) heure(19:31) normal(123456) " \ "séparateur (012.2345.12) signe + 12.2345.12 separateur 12,123,456 - 123 separateur 10 123 456 " \ "signe - 123.12 signe et sep -12,123 signe et sep -10 012,123 1456" print(cls.is_str(chaine, strip_num_char=True)) # affiche "Hello, voici ma liste avec des caractères numériques : date() heure() normal() séparateur () signe separateur separateur signe signe et sep signe et sep" # %% # remplacement des caractères, K -> A, i -> n et m -> T 3 -> 7 # 1er exemple avec une liste de caractères chaine = "Hello, ma \x12\x13\x14\x15\x16\x17\x18 chaine avec des caractères à remplacer : Kim Marie Adélie, ma petite choupinette a 3 ans (casse prise en coMpte...)" print(cls.is_str(chaine, chars_2_replace="Kim3", replaced_chars="AnT7")) # affiche "Hello, Ta channe avec des caractères à reTplacer : AnT Marne Adélne, Ta petnte choupnnette a 7 ans (casse prnse en coMpte...)" # %% # 2ème exemple avec un dictionnaire print(cls.is_str(chaine, chars_2_replace={ "Kim Marie Adélie": "Kim Marie Adélie TRUONG", # multi char "3": "7", # single char "M": "m" })) # Hello, ma chaine avec des caractères à remplacer : Kim Marie Adélie TRUONG, ma petite choupinette a 7 ans (casse prise en compte...)
-
corelibs.cleanse.
replace
(string, search, replace, regex_flag=None, encoding='Latin-1')¶ Description
Permet de remplacer la valeur d’une chaine de caractères avec un modèle regex ou une expression simple- Parameters
string – chaine de caractères à traiter
search – indique la chaine de caractères ou le modèle regex à chercher.
replace – indique la chaine de caractères ou le modèle regex en remplacement.
regex_flag – indique les flags à utiliser. cf. Liens utiles, Librairie regex pour plus de détails
encoding – indique l’encodage à la lecture/écriture
- Returns
- chaine de caractères transformée
Exemple :
# replace.py # %% import re from corelibs import config, cleanse as cls # %% # remplacement simple print( cls.replace( "Coucou Kim, c'est papa ❤ =}", "Kim", "Kim Marie Adélie" ) ) # affiche Coucou Kim Marie Adélie, c'est papa ❤ =} # remplacement simple (binaire, encodage latin) print( cls.replace( "Coucou Kim, c'est papa =}", # le coeur ne peut pas être utilisé ici car non présent dans l'encodage latin-1... sinon son code est 0xE2 0x99 0xA5 b"Kim", b"Kim Marie Ad\xE9lie", encoding=config.DEFAULT_ENCODING_FILE # "ISO-8859-1" ) ) # affiche Coucou Kim Marie Adélie, c'est papa =} # remplacement simple (binaire, encodage utf-8) print( cls.replace( "Coucou Kim, c'est papa ❤ =}", b"Kim", b"Kim Marie Ad\xC3\xA9lie", encoding="utf-8" ) ) # affiche Coucou Kim Marie Adélie, c'est papa ❤ =} # %% # remplacement avec regex (changement format date, AAAA-MM-DD deviendra DD/MM/AAAA) string = """ 999990583;00133;99999058300133;O;1993-01-01;NN;;;2006-11-25T22:25:28;false;4;CENTRALE DE MIJANES;;;;;09120;VARILHES;;;09324;;;;;;;;;;;;;;;;;;;2004-06-30;F;;;;;40.1A;NAFRev1;N 999990583;00158;99999058300158;O;1998-09-07;NN;;;2019-11-14T14:00:51;true;3;PARC TECHNOL LA PARDIEU;6;;RUE;CONDORCET;63000;CLERMONT-FERRAND;;;63113;;;;;;;;;;;;;;;;;;;2004-06-30;F;;;;;28.4A;NAFRev1;N 999990609;00011;99999060900011;O;;NN;;;;true;1;;4;;PL;DE LA PYRAMIDE;92800;PUTEAUX;;;92062;;;;;;;;;;;;;;;;;;;1991-12-30;F;;;;;73.1Z;NAF1993;N 999990625;00025;99999062500025;O;;NN;;;;true;1;;;;RTE;DE MANOM;57100;THIONVILLE;;;57672;;;;;;;;;;;;;;;;;;;1995-11-30;F;;;;;27.3C;NAF1993;O 999990641;00014;99999064100014;O;;NN;;;;true;1;;99;;BD;DE GRENELLE;75015;PARIS 15;;;75115;;;;;;;;;;;;;;;;;;;1986-06-15;F;;;;;65.01;NAP;N 999990666;00011;99999066600011;O;1986-05-15;;;;;false;4;;10;;RUE;CHAUCHAT;75009;PARIS 9;;;75109;;;;;;;;;;;;;;;;;;;1997-12-03;F;;;;;66.0A;NAF1993;N 999990666;00029;99999066600029;O;1997-12-03;;;;;false;3;;2;;RUE;PILLET WILL;75009;PARIS 9;;;75109;;;;;;;;;;;;;;;;;;;2000-07-01;F;;;;;66.0A;NAF1993;N 999990666;00037;99999066600037;O;2000-07-01;NN;;;2020-05-20T03:34:55;true;3;8 A 10;8;;RUE;D'ASTORG;75008;PARIS 8;;;75108;;;;;;;;;;;;;;;;;;;2008-01-01;A;;;;;65.11Z;NAFRev2;N 999990682;00034;99999068200034;O;2001-09-18;NN;;;;true;3;LE PONANT DE PARIS;27;;RUE;LEBLANC;75015;PARIS 15;;;75115;;;;;;;;;;;;;;;;;;;2003-12-18;F;;;;;65.2E;NAFRev1;N 999992357;00015;99999235700015;O;2003-12-31;01;2017;;2019-06-24T14:13:19;true;5;;6;;RUE;DE L ETOILE;80090;AMIENS;;;80021;;;;;;;;;;;;;;;;;;;2012-01-22;A;;;;;81.10Z;NAFRev2;O """ print( cls.replace( string, search=r"\b(\d{4})-(\d{2})-(\d{2})\b", replace=r"\3/\2/\1" ) ) # affiche (les champs dates sont bien modifiés comme souhaité, pas les champs horodatés comme AAAA-MM-DDTHH:MM) # 999990583;00133;99999058300133;O;01/01/1993;NN;;;2006-11-25T22:25:28;false;4;CENTRALE DE MIJANES;;;;;09120;VARILHES;;;09324;;;;;;;;;;;;;;;;;;;30/06/2004;F;;;;;40.1A;NAFRev1;N # 999990583;00158;99999058300158;O;07/09/1998;NN;;;2019-11-14T14:00:51;true;3;PARC TECHNOL LA PARDIEU;6;;RUE;CONDORCET;63000;CLERMONT-FERRAND;;;63113;;;;;;;;;;;;;;;;;;;30/06/2004;F;;;;;28.4A;NAFRev1;N # 999990609;00011;99999060900011;O;;NN;;;;true;1;;4;;PL;DE LA PYRAMIDE;92800;PUTEAUX;;;92062;;;;;;;;;;;;;;;;;;;30/12/1991;F;;;;;73.1Z;NAF1993;N # 999990625;00025;99999062500025;O;;NN;;;;true;1;;;;RTE;DE MANOM;57100;THIONVILLE;;;57672;;;;;;;;;;;;;;;;;;;30/11/1995;F;;;;;27.3C;NAF1993;O # 999990641;00014;99999064100014;O;;NN;;;;true;1;;99;;BD;DE GRENELLE;75015;PARIS 15;;;75115;;;;;;;;;;;;;;;;;;;15/06/1986;F;;;;;65.01;NAP;N # 999990666;00011;99999066600011;O;15/05/1986;;;;;false;4;;10;;RUE;CHAUCHAT;75009;PARIS 9;;;75109;;;;;;;;;;;;;;;;;;;03/12/1997;F;;;;;66.0A;NAF1993;N # 999990666;00029;99999066600029;O;03/12/1997;;;;;false;3;;2;;RUE;PILLET WILL;75009;PARIS 9;;;75109;;;;;;;;;;;;;;;;;;;01/07/2000;F;;;;;66.0A;NAF1993;N # 999990666;00037;99999066600037;O;01/07/2000;NN;;;2020-05-20T03:34:55;true;3;8 A 10;8;;RUE;D'ASTORG;75008;PARIS 8;;;75108;;;;;;;;;;;;;;;;;;;01/01/2008;A;;;;;65.11Z;NAFRev2;N # 999990682;00034;99999068200034;O;18/09/2001;NN;;;;true;3;LE PONANT DE PARIS;27;;RUE;LEBLANC;75015;PARIS 15;;;75115;;;;;;;;;;;;;;;;;;;18/12/2003;F;;;;;65.2E;NAFRev1;N # 999992357;00015;99999235700015;O;31/12/2003;01;2017;;2019-06-24T14:13:19;true;5;;6;;RUE;DE L ETOILE;80090;AMIENS;;;80021;;;;;;;;;;;;;;;;;;;22/01/2012;A;;;;;81.10Z;NAFRev2;O # %% # remplacement avec regex (changement format date + format horodaté, AAAA-MM-DD deviendra DD/MM/AAAA et AAAA-MM-DDTHH:MM deviendra DD/MM/AAAA HH:MM) print( cls.replace( cls.replace( string, search=r"\b(\d{4})-(\d{2})-(\d{2})\b", replace=r"\3/\2/\1" ), search=r"\b(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\b", replace=r"\3/\2/\1 \4:\5" ) ) # affiche (les champs dates et champs horodatés comme 2006-11-25T22 sont bien modifiés comme souhaité) # 999990583;00133;99999058300133;O;01/01/1993;NN;;;25/11/2006 22:25;false;4;CENTRALE DE MIJANES;;;;;09120;VARILHES;;;09324;;;;;;;;;;;;;;;;;;;30/06/2004;F;;;;;40.1A;NAFRev1;N # 999990583;00158;99999058300158;O;07/09/1998;NN;;;14/11/2019 14:00;true;3;PARC TECHNOL LA PARDIEU;6;;RUE;CONDORCET;63000;CLERMONT-FERRAND;;;63113;;;;;;;;;;;;;;;;;;;30/06/2004;F;;;;;28.4A;NAFRev1;N # 999990609;00011;99999060900011;O;;NN;;;;true;1;;4;;PL;DE LA PYRAMIDE;92800;PUTEAUX;;;92062;;;;;;;;;;;;;;;;;;;30/12/1991;F;;;;;73.1Z;NAF1993;N # 999990625;00025;99999062500025;O;;NN;;;;true;1;;;;RTE;DE MANOM;57100;THIONVILLE;;;57672;;;;;;;;;;;;;;;;;;;30/11/1995;F;;;;;27.3C;NAF1993;O # 999990641;00014;99999064100014;O;;NN;;;;true;1;;99;;BD;DE GRENELLE;75015;PARIS 15;;;75115;;;;;;;;;;;;;;;;;;;15/06/1986;F;;;;;65.01;NAP;N # 999990666;00011;99999066600011;O;15/05/1986;;;;;false;4;;10;;RUE;CHAUCHAT;75009;PARIS 9;;;75109;;;;;;;;;;;;;;;;;;;03/12/1997;F;;;;;66.0A;NAF1993;N # 999990666;00029;99999066600029;O;03/12/1997;;;;;false;3;;2;;RUE;PILLET WILL;75009;PARIS 9;;;75109;;;;;;;;;;;;;;;;;;;01/07/2000;F;;;;;66.0A;NAF1993;N # 999990666;00037;99999066600037;O;01/07/2000;NN;;;20/05/2020 03:34;true;3;8 A 10;8;;RUE;D'ASTORG;75008;PARIS 8;;;75108;;;;;;;;;;;;;;;;;;;01/01/2008;A;;;;;65.11Z;NAFRev2;N # 999990682;00034;99999068200034;O;18/09/2001;NN;;;;true;3;LE PONANT DE PARIS;27;;RUE;LEBLANC;75015;PARIS 15;;;75115;;;;;;;;;;;;;;;;;;;18/12/2003;F;;;;;65.2E;NAFRev1;N # 999992357;00015;99999235700015;O;31/12/2003;01;2017;;24/06/2019 14:13;true;5;;6;;RUE;DE L ETOILE;80090;AMIENS;;;80021;;;;;;;;;;;;;;;;;;;22/01/2012;A;;;;;81.10Z;NAFRev2;O # %% # remplacement avec regex & utilisation flags string = """ Tuesday 08 December 2020 - Ma log à moi que j'ai [termcolorlog.py:1] <> INFO : Bonjour, ceci est un test personnalisé niveau INFO Tuesday 08 December 2020 - Ma log à moi que j'ai [termcolorlog.py:1] <> WARNING : Bonjour, ceci est un test personnalisé niveau WARNING Tuesday 08 December 2020 - Ma log à moi que j'ai [termcolorlog.py:1] <> ERROR : Bonjour, ceci est un test personnalisé niveau ERROR Tuesday 08 December 2020 - Ma log à moi que j'ai [termcolorlog.py:1] <> CRITICAL : Bonjour, ceci est un test personnalisé niveau CRITIQUE """ print( cls.replace( string, search=r"^(tuesday) (08) (december) (2020)(.*)(Bonjour,)(.*)$", # justification de l'utilisation du flag re.I replace=r"\4/12/\2\5Au revoir!\7 - modifié par regex =}", regex_flag=re.M | re.I ) ) # affiche # 2020/12/08 - Ma log à moi que j'ai [termcolorlog.py:1] <> INFO : Au revoir! ceci est un test personnalisé niveau INFO - modifié par regex =} # 2020/12/08 - Ma log à moi que j'ai [termcolorlog.py:1] <> WARNING : Au revoir! ceci est un test personnalisé niveau WARNING - modifié par regex =} # 2020/12/08 - Ma log à moi que j'ai [termcolorlog.py:1] <> ERROR : Au revoir! ceci est un test personnalisé niveau ERROR - modifié par regex =} # 2020/12/08 - Ma log à moi que j'ai [termcolorlog.py:1] <> CRITICAL : Au revoir! ceci est un test personnalisé niveau CRITIQUE - modifié par regex =} # %% # remplacement binaire des espace par des ; print( cls.replace( string, search=b"\x20", replace=b"\x3B" ) ) # affiche # Tuesday;08;December;2020;-;Ma;log;à;moi;que;j'ai;[termcolorlog.py:1];<>;;;;;;;;;;INFO;:;Bonjour,;ceci;est;un;test;personnalisé;niveau;INFO # Tuesday;08;December;2020;-;Ma;log;à;moi;que;j'ai;[termcolorlog.py:1];<>;;;;;;;WARNING;:;Bonjour,;ceci;est;un;test;personnalisé;niveau;WARNING # Tuesday;08;December;2020;-;Ma;log;à;moi;que;j'ai;[termcolorlog.py:1];<>;;;;;;;;;ERROR;:;Bonjour,;ceci;est;un;test;personnalisé;niveau;ERROR # Tuesday;08;December;2020;-;Ma;log;à;moi;que;j'ai;[termcolorlog.py:1];<>;;;;;;CRITICAL;:;Bonjour,;ceci;est;un;test;personnalisé;niveau;CRITIQUE
-
corelibs.cleanse.
replace_chaining
(string, **kwargs)¶ Description
Wrapper de la fonctioncorelibs.cleanse.replace()
permettant de chaîner cette dernière, de manière à faciliter la lisibilité et optimiser les traitements de données- Parameters
string – chaine de caractères à traiter
kwargs – liste dynamique d’arguments nommés. Cette liste accepte toutes les données loufoques. Cependant seules les fonctions
corelibs.cleanse.replace()
etcorelibs.cleanse.is_str()
seront traitées (cf. Exemple pour plus de précisions)
- Returns
- chaine de caractères transformée
Exemples :
# replace_chaining.py # %% from corelibs import cleanse as cls, lazy as lz # %% # enchainement (plus lisible) string = """ 999990583;00133;99999058300133;O;1993-01-01;NN;;;2006-11-25T22:25:28;false;4;CENTRALE DE MIJANES;;;;;09120;VARILHES;;;09324;;;;;;;;;;;;;;;;;;;2004-06-30;F;;;;;40.1A;NAFRev1;N 999990583;00158;99999058300158;O;1998-09-07;NN;;;2019-11-14T14:00:51;true;3;PARC TECHNOL LA PARDIEU;6;;RUE;CONDORCET;63000;CLERMONT-FERRAND;;;63113;;;;;;;;;;;;;;;;;;;2004-06-30;F;;;;;28.4A;NAFRev1;N 999990609;00011;99999060900011;O;;NN;;;;true;1;;4;;PL;DE LA PYRAMIDE;92800;PUTEAUX;;;92062;;;;;;;;;;;;;;;;;;;1991-12-30;F;;;;;73.1Z;NAF1993;N 999990625;00025;99999062500025;O;;NN;;;;true;1;;;;RTE;DE MANOM;57100;THIONVILLE;;;57672;;;;;;;;;;;;;;;;;;;1995-11-30;F;;;;;27.3C;NAF1993;O 999990641;00014;99999064100014;O;;NN;;;;true;1;;99;;BD;DE GRENELLE;75015;PARIS 15;;;75115;;;;;;;;;;;;;;;;;;;1986-06-15;F;;;;;65.01;NAP;N 999990666;00011;99999066600011;O;1986-05-15;;;;;false;4;;10;;RUE;CHAUCHAT;75009;PARIS 9;;;75109;;;;;;;;;;;;;;;;;;;1997-12-03;F;;;;;66.0A;NAF1993;N 999990666;00029;99999066600029;O;1997-12-03;;;;;false;3;;2;;RUE;PILLET WILL;75009;PARIS 9;;;75109;;;;;;;;;;;;;;;;;;;2000-07-01;F;;;;;66.0A;NAF1993;N 999990666;00037;99999066600037;O;2000-07-01;NN;;;2020-05-20T03:34:55;true;3;8 A 10;8;;RUE;D'ASTORG;75008;PARIS 8;;;75108;;;;;;;;;;;;;;;;;;;2008-01-01;A;;;;;65.11Z;NAFRev2;N 999990682;00034;99999068200034;O;2001-09-18;NN;;;;true;3;LE PONANT DE PARIS;27;;RUE;LEBLANC;75015;PARIS 15;;;75115;;;;;;;;;;;;;;;;;;;2003-12-18;F;;;;;65.2E;NAFRev1;N 999992357;00015;99999235700015;O;2003-12-31;01;2017;;2019-06-24T14:13:19;true;5;;6;;RUE;DE L ETOILE;80090;AMIENS;;;80021;;;;;;;;;;;;;;;;;;;2012-01-22;A;;;;;81.10Z;NAFRev2;O """ res = cls.replace_chaining( string, udf_1=lambda x: cls.replace(x, r"\b(\d{4})-(\d{2})-(\d{2})\b", r"\3/\2/\1"), # transformation AAAA-MM-DD en DD/MM/AAAA udf_3=lambda x: cls.replace(x, r"\b(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\b", r"\3/\2/\1 \4:\5"), # transformation AAAA-MM-DDTHH:MM en DD/MM/AAAA HH:MM arg_dynamique="Coucou", # ne sera pas traité car n'est pas un callable function_dynamique=lz.get_home, # callable mais ne sera pas non plus traité car n'est pas un replace() switch_separator=lambda x: cls.replace(x, b"\x3B", b"\x7C") # remplacer les ; en | comme caractère séparateur # liste infinie dynamique des fonctions appelables à la suite... (si utile et pertinent) ) print(res) # affiche # 999990583|00133|99999058300133|O|01/01/1993|NN|||25/11/2006 22:25|false|4|CENTRALE DE MIJANES|||||09120|VARILHES|||09324|||||||||||||||||||30/06/2004|F|||||40.1A|NAFRev1|N # 999990583|00158|99999058300158|O|07/09/1998|NN|||14/11/2019 14:00|true|3|PARC TECHNOL LA PARDIEU|6||RUE|CONDORCET|63000|CLERMONT-FERRAND|||63113|||||||||||||||||||30/06/2004|F|||||28.4A|NAFRev1|N # 999990609|00011|99999060900011|O||NN||||true|1||4||PL|DE LA PYRAMIDE|92800|PUTEAUX|||92062|||||||||||||||||||30/12/1991|F|||||73.1Z|NAF1993|N # 999990625|00025|99999062500025|O||NN||||true|1||||RTE|DE MANOM|57100|THIONVILLE|||57672|||||||||||||||||||30/11/1995|F|||||27.3C|NAF1993|O # 999990641|00014|99999064100014|O||NN||||true|1||99||BD|DE GRENELLE|75015|PARIS 15|||75115|||||||||||||||||||15/06/1986|F|||||65.01|NAP|N # 999990666|00011|99999066600011|O|15/05/1986|||||false|4||10||RUE|CHAUCHAT|75009|PARIS 9|||75109|||||||||||||||||||03/12/1997|F|||||66.0A|NAF1993|N # 999990666|00029|99999066600029|O|03/12/1997|||||false|3||2||RUE|PILLET WILL|75009|PARIS 9|||75109|||||||||||||||||||01/07/2000|F|||||66.0A|NAF1993|N # 999990666|00037|99999066600037|O|01/07/2000|NN|||20/05/2020 03:34|true|3|8 A 10|8||RUE|D'ASTORG|75008|PARIS 8|||75108|||||||||||||||||||01/01/2008|A|||||65.11Z|NAFRev2|N # 999990682|00034|99999068200034|O|18/09/2001|NN||||true|3|LE PONANT DE PARIS|27||RUE|LEBLANC|75015|PARIS 15|||75115|||||||||||||||||||18/12/2003|F|||||65.2E|NAFRev1|N # 999992357|00015|99999235700015|O|31/12/2003|01|2017||24/06/2019 14:13|true|5||6||RUE|DE L ETOILE|80090|AMIENS|||80021|||||||||||||||||||22/01/2012|A|||||81.10Z|NAFRev2|O # %% # sinon en version non enchainée, 1ère possibilité (imbrication) print( cls.replace( cls.replace( cls.replace( string, search=r"\b(\d{4})-(\d{2})-(\d{2})\b", replace=r"\3/\2/\1" ), search=r"\b(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\b", replace=r"\3/\2/\1 \4:\5" ), b"\x3B", b"\x7C" ) ) # affiche bien l'attendu # 999990583|00133|99999058300133|O|01/01/1993|NN|||25/11/2006 22:25|false|4|CENTRALE DE MIJANES|||||09120|VARILHES|||09324|||||||||||||||||||30/06/2004|F|||||40.1A|NAFRev1|N # 999990583|00158|99999058300158|O|07/09/1998|NN|||14/11/2019 14:00|true|3|PARC TECHNOL LA PARDIEU|6||RUE|CONDORCET|63000|CLERMONT-FERRAND|||63113|||||||||||||||||||30/06/2004|F|||||28.4A|NAFRev1|N # 999990609|00011|99999060900011|O||NN||||true|1||4||PL|DE LA PYRAMIDE|92800|PUTEAUX|||92062|||||||||||||||||||30/12/1991|F|||||73.1Z|NAF1993|N # 999990625|00025|99999062500025|O||NN||||true|1||||RTE|DE MANOM|57100|THIONVILLE|||57672|||||||||||||||||||30/11/1995|F|||||27.3C|NAF1993|O # 999990641|00014|99999064100014|O||NN||||true|1||99||BD|DE GRENELLE|75015|PARIS 15|||75115|||||||||||||||||||15/06/1986|F|||||65.01|NAP|N # 999990666|00011|99999066600011|O|15/05/1986|||||false|4||10||RUE|CHAUCHAT|75009|PARIS 9|||75109|||||||||||||||||||03/12/1997|F|||||66.0A|NAF1993|N # 999990666|00029|99999066600029|O|03/12/1997|||||false|3||2||RUE|PILLET WILL|75009|PARIS 9|||75109|||||||||||||||||||01/07/2000|F|||||66.0A|NAF1993|N # 999990666|00037|99999066600037|O|01/07/2000|NN|||20/05/2020 03:34|true|3|8 A 10|8||RUE|D'ASTORG|75008|PARIS 8|||75108|||||||||||||||||||01/01/2008|A|||||65.11Z|NAFRev2|N # 999990682|00034|99999068200034|O|18/09/2001|NN||||true|3|LE PONANT DE PARIS|27||RUE|LEBLANC|75015|PARIS 15|||75115|||||||||||||||||||18/12/2003|F|||||65.2E|NAFRev1|N # 999992357|00015|99999235700015|O|31/12/2003|01|2017||24/06/2019 14:13|true|5||6||RUE|DE L ETOILE|80090|AMIENS|||80021|||||||||||||||||||22/01/2012|A|||||81.10Z|NAFRev2|O # %% # sinon en version non enchainée, 2ème possibilité (avec étapes intermédiaires) etape_1 = cls.replace( string, search=r"\b(\d{4})-(\d{2})-(\d{2})\b", replace=r"\3/\2/\1" ) etape_2 = cls.replace( etape_1, search=r"\b(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\b", replace=r"\3/\2/\1 \4:\5" ) print( cls.replace( etape_2, search=b"\x3B", replace=b"\x7C" ) ) # affiche bien l'attendu # 999990583|00133|99999058300133|O|01/01/1993|NN|||25/11/2006 22:25|false|4|CENTRALE DE MIJANES|||||09120|VARILHES|||09324|||||||||||||||||||30/06/2004|F|||||40.1A|NAFRev1|N # 999990583|00158|99999058300158|O|07/09/1998|NN|||14/11/2019 14:00|true|3|PARC TECHNOL LA PARDIEU|6||RUE|CONDORCET|63000|CLERMONT-FERRAND|||63113|||||||||||||||||||30/06/2004|F|||||28.4A|NAFRev1|N # 999990609|00011|99999060900011|O||NN||||true|1||4||PL|DE LA PYRAMIDE|92800|PUTEAUX|||92062|||||||||||||||||||30/12/1991|F|||||73.1Z|NAF1993|N # 999990625|00025|99999062500025|O||NN||||true|1||||RTE|DE MANOM|57100|THIONVILLE|||57672|||||||||||||||||||30/11/1995|F|||||27.3C|NAF1993|O # 999990641|00014|99999064100014|O||NN||||true|1||99||BD|DE GRENELLE|75015|PARIS 15|||75115|||||||||||||||||||15/06/1986|F|||||65.01|NAP|N # 999990666|00011|99999066600011|O|15/05/1986|||||false|4||10||RUE|CHAUCHAT|75009|PARIS 9|||75109|||||||||||||||||||03/12/1997|F|||||66.0A|NAF1993|N # 999990666|00029|99999066600029|O|03/12/1997|||||false|3||2||RUE|PILLET WILL|75009|PARIS 9|||75109|||||||||||||||||||01/07/2000|F|||||66.0A|NAF1993|N # 999990666|00037|99999066600037|O|01/07/2000|NN|||20/05/2020 03:34|true|3|8 A 10|8||RUE|D'ASTORG|75008|PARIS 8|||75108|||||||||||||||||||01/01/2008|A|||||65.11Z|NAFRev2|N # 999990682|00034|99999068200034|O|18/09/2001|NN||||true|3|LE PONANT DE PARIS|27||RUE|LEBLANC|75015|PARIS 15|||75115|||||||||||||||||||18/12/2003|F|||||65.2E|NAFRev1|N # 999992357|00015|99999235700015|O|31/12/2003|01|2017||24/06/2019 14:13|true|5||6||RUE|DE L ETOILE|80090|AMIENS|||80021|||||||||||||||||||22/01/2012|A|||||81.10Z|NAFRev2|O
# replace_chaining_AL.py # exemple programme pour gérer le mailing list d'Alex L. from corelibs import cleanse as cls # %% with open(r"D:\OneDrive\Desktop\Alex_L_LD.txt") as f_in: string = f_in.read() def name_2_upper(m): return m.groups()[1] + " " + m.groups()[0].upper()[:-1] + " " + m.groups()[2] def mail_2_name(m): return m.groups()[0].title() + " " + m.groups()[1].upper() + \ " <" + m.groups()[0].lower() + "." + m.groups()[1].lower() + m.groups()[2].lower() + ">" res = cls.replace_chaining( string, udf_0=lambda x: cls.is_str(x, chars_2_replace={ # nettoyage caractères zarbioïdes "é": "é", "ô": "ô", "ç": "ç", "Ç": "Ç" }), udf_1=lambda x: cls.replace(x, r"((([-\w',çéô Ç]* )*(<[-\w.@]*>)|([\w .@]*)))(;)", r"\1\n"), # séparer en liste udf_2=lambda x: cls.replace(x, r"(^[ ]+)?(.*)", r"\2"), # suppression démarrage par espace(s) udf_3=lambda x: cls.replace(x, r"'(.*),? (.*)' (.*)", name_2_upper), # gestion modèle sous forme "Prénoms Composés NOMS COMPOSÉS <email>" udf_4=lambda x: cls.replace(x, r"^(?!(?:DOCUMENTATION).*$)(\w*).(\w*)(@[\w.]*)", mail_2_name), # gestion modèle sous forme "prenom.nom@bpifrance.fr" sans prendre en compte le cas particulier "DOCUMENTATION documentation@bpifrance.fr" udf_5=lambda x: cls.replace(x, r"(([A-Z][-,a-zéèôç. ']+[ ]*)+) (([-A-Z ]+) ?)+ <(.*)>", r"\1;\3;\5"), # formatage final Prénom Composé;NOMS COMPOSÉS;email@domain udf_6=lambda x: cls.replace(x, r"^(?!(.*;){2}(.*))([\w\- ]+) <?([\w.@]*)>?", r"\3;;\4;VALIDATION MANUELLE"), # tout le reste, à surveiller manuellement car les formatages n'ont pas été identifiés par les schémas ci-dessus... ) # affichage sortie standard print(res) # ou sortie vers fichier with open(r"D:\OneDrive\Desktop\Alex_L_LD_FORMATED.txt", "w") as f_out: f_out.write(res)
Exemple Appel depuis R :
# treticulate_clease.r # exemple appel des fonctions du package corelibs depuis R... # //! install.packages("reticulate") # si n'existe pas... # //! install.packages("readr") library("reticulate") library(readr) reticulate::use_condaenv(condaenv="test_conda", required=TRUE) cleanse <- reticulate::import("corelibs.cleanse", delay_load=TRUE) file_2_cleanse <- read_file(file="D:\\OneDrive\\Desktop\\Alex_L_LD.txt") data <- cleanse$is_str(file_2_cleanse, chars_2_replace="é", replaced_chars="é") data <- cleanse$is_str(file_2_cleanse, chars_2_replace="ô", replaced_chars="ô") data <- cleanse$is_str(file_2_cleanse, chars_2_replace="ç", replaced_chars="ç") data <- cleanse$is_str(file_2_cleanse, chars_2_replace="Ç", replaced_chars="Ç") data <- cleanse$replace( data, search="((([-\\w',çéô Ç]* )*(<[-\\w.@]*>)|([\\w .@]*)))(;)", replace="\\1\\n" ) data <- cleanse$replace(data, "(^[ ]+)?(.*)", "\\2") f <- py_run_string(" def name_2_upper(m): return m.groups()[1] + \" \" + m.groups()[0].upper()[:-1] + \" \" + m.groups()[2] ") data <- cleanse$replace( data, "'(.*),? (.*)' (.*)", f$name_2_upper ) f <- py_run_string(" def mail_2_name(m): return m.groups()[0].title() + \" \" + m.groups()[1].upper() + \\ \" <\" + m.groups()[0].lower() + \".\" + m.groups()[1].lower() + m.groups()[2].lower() + \">\" ") data <- cleanse$replace( data, "^(?!(?:DOCUMENTATION).*$)(\\w*).(\\w*)(@[\\w.]*)", f$mail_2_name ) data <- cleanse$replace( data, "(([A-Z][-,a-zéèôç. ']+[ ]*)+) (([-A-Z ]+) ?)+ <(.*)>", "\\1;\\3;\\5" ) data <- cleanse$replace( data, "^(?!(.*;){2}(.*))([\\w\\- ]+) <?([\\w.@]*)>?", "\\3;;\\4;VALIDATION MANUELLE" ) f_out <- file("D:\\OneDrive\\Desktop\\Alex_L_LD_FORMATED_BY_R.txt") writeLines(data, f_out) close(f_out)
-
corelibs.cleanse.
strip
(string, search=None, replace='', non_printable_char=True, non_breaking_space=True, multi_space=True, empty_line=True, accented_char=False, num_char=False, unicode_categories=None, regex_flag=None, encoding='Latin-1')¶ Description
Permet d’enlever des caractères ou chaines de caractères avec un modèle ou expressionNote
strip() a le même comportement quecorelibs.cleanse.replace()
si replace prend une valeur différente de vide. l’intérêt de strip() est d’avoir des modèles prédéfinis pour purifier les fichiers et/ou des chaînes de caractères avec des caractères loufoques- Parameters
string – chaine de caractères à traiter
search – indique la chaine de caractères ou le modèle regex à chercher (si les autres options ne répondent pas aux besoins).
replace – indique le caractère ou la chaîne de caractères de remplacement (rien par défaut)
non_printable_char –
indique la suppression de tous les caracètres non imprimables
valeurs possibles: False/Truevaleur par défaut: Truenon_breaking_space –
indique la suppression de tous les espaces insécables (non breaking space)
valeurs possibles: False/Truevaleur par défaut: Truemulti_space –
indique la suppression des multiple espaces contigüs par un seul espace
valeurs possibles: False/Truevaleur par défaut: Trueempty_line –
indique la suppression des lignes vides
valeurs possibles: False/Truevaleur par défaut: Trueaccented_char –
indique la suppression des caractères accentués
valeurs possibles: False/Truevaleur par défaut: Falsenum_char –
indique la suppression des caractères contenant des valeurs numériques (formatées ou non)
valeurs possibles: False/Truevaleur par défaut: Falseunicode_categories –
permet de spécifier une classe de caractères Unicode à supprimer.
valeurs possibles: Liste ou Tuple de classe Unicode (cf. Classification des caractères Unicodes pour plus de détails sur les classifications des caractères Unicodes)regex_flag – indique les flags à utiliser. cf. Liens utiles, Librairie regex pour plus de détails
encoding – indique l’encodage à la lecture/écriture
- Returns
- chaine de caractères transformée
Exemple :
# strip.py # %% from corelibs import cleanse as cls # %% # suppression de tous les caractères non imprimables # \x00 <=> NULL (NUL) # \x01 <=> START OF HEADING (SOH) # \x02 <=> START OF TEXT (STX) # \x03 <=> END OF TEXT (ETX) # \x04 <=> END OF TRANSMISSION (EOT) # \x05 <=> END OF QUERY (ENQ) # \x06 <=> ACKNOWLEDGE (ACK) # \x07 <=> BEEP (BEL) # \x08 <=> BACKSPACE (BS) # \x09 <=> HORIZONTAL TAB (HT) # \x0A <=> LINE FEED (LF) # \x0B <=> VERTICAL TAB (VT) # \x0C <=> FORM FEED (FF) # \x0D <=> CARRIAGE RETURN (CR) # \x0E <=> SHIFT OUT (SO) # \x0F <=> SHIFT IN (SI) # \x10 <=> DATA LINK ESCAPE (DLE) # \x11 <=> DEVICE CONTROL 1 (DC1) # \x12 <=> DEVICE CONTROL 2 (DC2) # \x13 <=> DEVICE CONTROL 3 (DC3) # \x14 <=> DEVICE CONTROL 4 (DC4) # \x15 <=> NEGATIVE ACKNOWLEDGEMENT (NAK) # \x16 <=> SYNCHRONIZE (SYN) # \x17 <=> END OF TRANSMISSION BLOCK (ETB) # \x18 <=> CANCEL (CAN) # \x19 <=> END OF MEDIUM (EM) # \x1A <=> SUBSTITUTE (SUB) # \x1B <=> ESCAPE (ESC) # \x1C <=> FILE SEPARATOR (FS) RIGHT ARROW # \x1D <=> GROUP SEPARATOR (GS) LEFT ARROW # \x1E <=> RECORD SEPARATOR (RS) UP ARROW # \x1F <=> UNIT SEPARATOR (US) DOWN ARROW string = """ \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19 \x1A\x1B\x1C\x1D\x1E\x1F Hello, je suis la chaîne qui va rester après nettoyage... \x12\x13\x14\x15\x16\x17\x18 ❤ =} """ print(cls.strip(string)) # affiche " Hello, je suis la chaîne qui va rester après nettoyage... ❤ =}" # %% # supression de tous les caractères non imprimables, avec un remplacement différent print(cls.strip(string, replace="-")) # affiche "-----------------------------------Hello,-je-suis-la-chaîne-qui-va-rester-après-nettoyage...---------❤-=}-" # %% # Supression via des classes de caractères Unicode # Cc => Caractères de contrôles (non imprimables) # Lu => Caractères majuscules # Zs => espace print(cls.strip(string, unicode_categories=("Cc", "Lu", "Zs"))) # affiche "ello,jesuislachaînequivaresteraprèsnettoyage...❤=}" # %% # Supression multiple espaces (comportement par défaut) string = """ \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19 o( ^ ^ o) Hello Kim !!! (o ^ ^ )o \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19 """ print(cls.strip(string)) # affiche "o( ^ ^ o) Hello Kim !!! (o ^ ^ )o" # %% # Supression espace insécable string = "Cette chaine contient 3 espaces -(\xA0\xA0\xA0)- insécables" print(string) # affiche "Cette chaine contient 3 espaces -( )- insécables" print(cls.strip(string)) # affiche "Cette chaine contient 3 espaces -()- insécables" # %% # suppression des caractères accentués en les ramplaçant par leurs équivalents non accentués string = "Hello, voici ma liste de caractères accentués ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿŒœŠšŸƒ" print(cls.strip(string, accented_char=True)) # affiche "Hello, voici ma liste de caracteres accentues AAAAAAÆCEEEEIIIIÐNOOOOOØUUUUYÞßaaaaaaæceeeeiiiiðnoooooøuuuuyþyŒœSsYƒ" # %% # suppression des caractères numériques avec les signes, opérateurs et séparateurs string = """ Hello, voici ma liste avec des caractères numériques : date -(28/11/2013)- heure -(19:31)- normal -(123456)- signe -(+ 12.2345.12)- ou -(- 12.2345.12)- séparateur -(012.2345.12)- ou -(12,123,456)- ou -( 10 123 456)- signe et sep -(-10 012,123 1456)- """ print(cls.strip(string, num_char=True, non_printable_char=False)) # affiche " # Hello, voici ma liste avec des caractères numériques : # date -()- # heure -()- # normal -()- # signe -()- ou -()- # séparateur -()- ou -()- ou -()- # signe et sep -()- # " # %% # suppression par recherche standard (on enlève ici tout ce qui est entre les ; - juste pour le fun car aucun intérêt...) string = """ 999990583;00133;99999058300133;O;1993-01-01;NN;;;2006-11-25T22:25:28;false;4;CENTRALE DE MIJANES;;;;;09120;VARILHES;;;09324;;;;;;;;;;;;;;;;;;;2004-06-30;F;;;;;40.1A;NAFRev1;N 999990583;00158;99999058300158;O;1998-09-07;NN;;;2019-11-14T14:00:51;true;3;PARC TECHNOL LA PARDIEU;6;;RUE;CONDORCET;63000;CLERMONT-FERRAND;;;63113;;;;;;;;;;;;;;;;;;;2004-06-30;F;;;;;28.4A;NAFRev1;N 999990609;00011;99999060900011;O;;NN;;;;true;1;;4;;PL;DE LA PYRAMIDE;92800;PUTEAUX;;;92062;;;;;;;;;;;;;;;;;;;1991-12-30;F;;;;;73.1Z;NAF1993;N 999990625;00025;99999062500025;O;;NN;;;;true;1;;;;RTE;DE MANOM;57100;THIONVILLE;;;57672;;;;;;;;;;;;;;;;;;;1995-11-30;F;;;;;27.3C;NAF1993;O 999990641;00014;99999064100014;O;;NN;;;;true;1;;99;;BD;DE GRENELLE;75015;PARIS 15;;;75115;;;;;;;;;;;;;;;;;;;1986-06-15;F;;;;;65.01;NAP;N 999990666;00011;99999066600011;O;1986-05-15;;;;;false;4;;10;;RUE;CHAUCHAT;75009;PARIS 9;;;75109;;;;;;;;;;;;;;;;;;;1997-12-03;F;;;;;66.0A;NAF1993;N 999990666;00029;99999066600029;O;1997-12-03;;;;;false;3;;2;;RUE;PILLET WILL;75009;PARIS 9;;;75109;;;;;;;;;;;;;;;;;;;2000-07-01;F;;;;;66.0A;NAF1993;N 999990666;00037;99999066600037;O;2000-07-01;NN;;;2020-05-20T03:34:55;true;3;8 A 10;8;;RUE;D'ASTORG;75008;PARIS 8;;;75108;;;;;;;;;;;;;;;;;;;2008-01-01;A;;;;;65.11Z;NAFRev2;N 999990682;00034;99999068200034;O;2001-09-18;NN;;;;true;3;LE PONANT DE PARIS;27;;RUE;LEBLANC;75015;PARIS 15;;;75115;;;;;;;;;;;;;;;;;;;2003-12-18;F;;;;;65.2E;NAFRev1;N 999992357;00015;99999235700015;O;2003-12-31;01;2017;;2019-06-24T14:13:19;true;5;;6;;RUE;DE L ETOILE;80090;AMIENS;;;80021;;;;;;;;;;;;;;;;;;;2012-01-22;A;;;;;81.10Z;NAFRev2;O """ print(cls.strip(string, search=r"[^;\n]+", non_printable_char=False)) # affiche " # ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; # ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; # ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; # ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; # ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; # ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; # ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; # ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; # ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; # ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; # " # %% # suppression des ; avec remplacement par , (en binaire) print(cls.strip(string, search=b"\x3B", non_printable_char=False, replace=b"\x2C")) # affiche " # 999990583,00133,99999058300133,O,1993-01-01,NN,,,2006-11-25T22:25:28,false,4,CENTRALE,DE,MIJANES,,,,,09120,VARILHES,,,09324,,,,,,,,,,,,,,,,,,,2004-06-30,F,,,,,40.1A,NAFRev1,N # 999990583,00158,99999058300158,O,1998-09-07,NN,,,2019-11-14T14:00:51,true,3,PARC,TECHNOL,LA,PARDIEU,6,,RUE,CONDORCET,63000,CLERMONT-FERRAND,,,63113,,,,,,,,,,,,,,,,,,,2004-06-30,F,,,,,28.4A,NAFRev1,N # 999990609,00011,99999060900011,O,,NN,,,,true,1,,4,,PL,DE,LA,PYRAMIDE,92800,PUTEAUX,,,92062,,,,,,,,,,,,,,,,,,,1991-12-30,F,,,,,73.1Z,NAF1993,N # 999990625,00025,99999062500025,O,,NN,,,,true,1,,,,RTE,DE,MANOM,57100,THIONVILLE,,,57672,,,,,,,,,,,,,,,,,,,1995-11-30,F,,,,,27.3C,NAF1993,O # 999990641,00014,99999064100014,O,,NN,,,,true,1,,99,,BD,DE,GRENELLE,75015,PARIS,15,,,75115,,,,,,,,,,,,,,,,,,,1986-06-15,F,,,,,65.01,NAP,N # 999990666,00011,99999066600011,O,1986-05-15,,,,,false,4,,10,,RUE,CHAUCHAT,75009,PARIS,9,,,75109,,,,,,,,,,,,,,,,,,,1997-12-03,F,,,,,66.0A,NAF1993,N # 999990666,00029,99999066600029,O,1997-12-03,,,,,false,3,,2,,RUE,PILLET,WILL,75009,PARIS,9,,,75109,,,,,,,,,,,,,,,,,,,2000-07-01,F,,,,,66.0A,NAF1993,N # 999990666,00037,99999066600037,O,2000-07-01,NN,,,2020-05-20T03:34:55,true,3,8,A,10,8,,RUE,D'ASTORG,75008,PARIS,8,,,75108,,,,,,,,,,,,,,,,,,,2008-01-01,A,,,,,65.11Z,NAFRev2,N # 999990682,00034,99999068200034,O,2001-09-18,NN,,,,true,3,LE,PONANT,DE,PARIS,27,,RUE,LEBLANC,75015,PARIS,15,,,75115,,,,,,,,,,,,,,,,,,,2003-12-18,F,,,,,65.2E,NAFRev1,N # 999992357,00015,99999235700015,O,2003-12-31,01,2017,,2019-06-24T14:13:19,true,5,,6,,RUE,DE,L,ETOILE,80090,AMIENS,,,80021,,,,,,,,,,,,,,,,,,,2012-01-22,A,,,,,81.10Z,NAFRev2,O # " # %% # suppression lignes vides string = """ 999990609,00011,99999060900011,O,,NN,,,,true,1,,4,,PL,DE,LA,PYRAMIDE,92800,PUTEAUX,,,92062,,,,,,,,,,,,,,,,,,,1991-12-30,F,,,,,73.1Z,NAF1993,N 999990625,00025,99999062500025,O,,NN,,,,true,1,,,,RTE,DE,MANOM,57100,THIONVILLE,,,57672,,,,,,,,,,,,,,,,,,,1995-11-30,F,,,,,27.3C,NAF1993,O 999990666,00011,99999066600011,O,1986-05-15,,,,,false,4,,10,,RUE,CHAUCHAT,75009,PARIS,9,,,75109,,,,,,,,,,,,,,,,,,,1997-12-03,F,,,,,66.0A,NAF1993,N 999990666,00029,99999066600029,O,1997-12-03,,,,,false,3,,2,,RUE,PILLET,WILL,75009,PARIS,9,,,75109,,,,,,,,,,,,,,,,,,,2000-07-01,F,,,,,66.0A,NAF1993,N """ print(cls.strip(string, non_printable_char=False)) # affiche # 999990609,00011,99999060900011,O,,NN,,,,true,1,,4,,PL,DE,LA,PYRAMIDE,92800,PUTEAUX,,,92062,,,,,,,,,,,,,,,,,,,1991-12-30,F,,,,,73.1Z,NAF1993,N # 999990625,00025,99999062500025,O,,NN,,,,true,1,,,,RTE,DE,MANOM,57100,THIONVILLE,,,57672,,,,,,,,,,,,,,,,,,,1995-11-30,F,,,,,27.3C,NAF1993,O # 999990666,00011,99999066600011,O,1986-05-15,,,,,false,4,,10,,RUE,CHAUCHAT,75009,PARIS,9,,,75109,,,,,,,,,,,,,,,,,,,1997-12-03,F,,,,,66.0A,NAF1993,N # 999990666,00029,99999066600029,O,1997-12-03,,,,,false,3,,2,,RUE,PILLET,WILL,75009,PARIS,9,,,75109,,,,,,,,,,,,,,,,,,,2000-07-01,F,,,,,66.0A,NAF1993,N
-
corelibs.cleanse.
strip_chaining
(string, **kwargs)¶ Description
Wrapper de la fonctioncorelibs.cleanse.strip()
permettant de chaîner cette dernière, de manière à faciliter la lisibilité et optimiser les traitements de données- Parameters
string – chaine de caractères à traiter
kwargs – liste dynamique d’arguments nommés. Cette liste accepte toutes les données loufoques. Cependant seules les fonctions
corelibs.cleanse.strip()
seront traitées (cf. Exemple pour plus de précisions)
- Returns
- chaine de caractères transformée
Exemple :
# replace_chaining.py # %% from corelibs import cleanse as cls, lazy as lz # %% # enchainement (plus lisible) string = """ 999990583;00133;99999058300133;O;1993-01-01;NN;;;2006-11-25T22:25:28;false;4;CENTRALE DE MIJANES;;;;;09120;VARILHES;;;09324;;;;;;;;;;;;;;;;;;;2004-06-30;F;;;;;40.1A;NAFRev1;N 999990583;00158;99999058300158;O;1998-09-07;NN;;;2019-11-14T14:00:51;true;3;PARC TECHNOL LA PARDIEU;6;;RUE;CONDORCET;63000;CLERMONT-FERRAND;;;63113;;;;;;;;;;;;;;;;;;;2004-06-30;F;;;;;28.4A;NAFRev1;N 999990609;00011;99999060900011;O;;NN;;;;true;1;;4;;PL;DE LA PYRAMIDE;92800;PUTEAUX;;;92062;;;;;;;;;;;;;;;;;;;1991-12-30;F;;;;;73.1Z;NAF1993;N 999990625;00025;99999062500025;O;;NN;;;;true;1;;;;RTE;DE MANOM;57100;THIONVILLE;;;57672;;;;;;;;;;;;;;;;;;;1995-11-30;F;;;;;27.3C;NAF1993;O 999990641;00014;99999064100014;O;;NN;;;;true;1;;99;;BD;DE GRENELLE;75015;PARIS 15;;;75115;;;;;;;;;;;;;;;;;;;1986-06-15;F;;;;;65.01;NAP;N 999990666;00011;99999066600011;O;1986-05-15;;;;;false;4;;10;;RUE;CHAUCHAT;75009;PARIS 9;;;75109;;;;;;;;;;;;;;;;;;;1997-12-03;F;;;;;66.0A;NAF1993;N 999990666;00029;99999066600029;O;1997-12-03;;;;;false;3;;2;;RUE;PILLET WILL;75009;PARIS 9;;;75109;;;;;;;;;;;;;;;;;;;2000-07-01;F;;;;;66.0A;NAF1993;N 999990666;00037;99999066600037;O;2000-07-01;NN;;;2020-05-20T03:34:55;true;3;8 A 10;8;;RUE;D'ASTORG;75008;PARIS 8;;;75108;;;;;;;;;;;;;;;;;;;2008-01-01;A;;;;;65.11Z;NAFRev2;N 999990682;00034;99999068200034;O;2001-09-18;NN;;;;true;3;LE PONANT DE PARIS;27;;RUE;LEBLANC;75015;PARIS 15;;;75115;;;;;;;;;;;;;;;;;;;2003-12-18;F;;;;;65.2E;NAFRev1;N 999992357;00015;99999235700015;O;2003-12-31;01;2017;;2019-06-24T14:13:19;true;5;;6;;RUE;DE L ETOILE;80090;AMIENS;;;80021;;;;;;;;;;;;;;;;;;;2012-01-22;A;;;;;81.10Z;NAFRev2;O """ res = cls.strip_chaining( string, arg_dynamique="Coucou", # ne sera pas traité car n'est pas un callable function_dynamique=lz.get_home, # callable mais ne sera pas non plus traité car n'est pas un strip() # liste infinie dynamique des fonctions appelables à la suite... (si utile et pertinent) udf_1=lambda x: cls.strip(x, search=r"\d{9};00[1-9]{3};.*", non_printable_char=False), # suppression de tous les siren avec un NIC 00XXXX (en ne gardant plus que les NIC à 000XX) udf_2=lambda x: cls.strip(x, search=b"\x3B", non_printable_char=False, replace=b"\x2C"), udf_3=lambda x: cls.strip(x, search=r".*,(NAFRev\d*|NAP).*", non_printable_char=False) # suppression de tous les NAF non définitifs ou les valeurs NAP qui semblent être incorrects ) print(res) # affiche # 999990609,00011,99999060900011,O,,NN,,,,true,1,,4,,PL,DE,LA,PYRAMIDE,92800,PUTEAUX,,,92062,,,,,,,,,,,,,,,,,,,1991-12-30,F,,,,,73.1Z,NAF1993,N # 999990625,00025,99999062500025,O,,NN,,,,true,1,,,,RTE,DE,MANOM,57100,THIONVILLE,,,57672,,,,,,,,,,,,,,,,,,,1995-11-30,F,,,,,27.3C,NAF1993,O # 999990666,00011,99999066600011,O,1986-05-15,,,,,false,4,,10,,RUE,CHAUCHAT,75009,PARIS,9,,,75109,,,,,,,,,,,,,,,,,,,1997-12-03,F,,,,,66.0A,NAF1993,N # 999990666,00029,99999066600029,O,1997-12-03,,,,,false,3,,2,,RUE,PILLET,WILL,75009,PARIS,9,,,75109,,,,,,,,,,,,,,,,,,,2000-07-01,F,,,,,66.0A,NAF1993,N # %% # sinon en version non enchainée, 1ère possibilité (imbrication) print( cls.strip( cls.strip( cls.strip( string, search=r"\d{9};00[1-9]{3};.*", # suppression de tous les siren avec un NIC 00XXXX (en ne gardant plus que les NIC à 000XX) non_printable_char=False ), search=b"\x3B", replace=b"\x2C", non_printable_char=False ), search=r".*,(NAFRev\d*|NAP).*", # suppression de tous les NAF non définitifs ou les valeurs NAP qui semblent être incorrects non_printable_char=False ) ) # affiche bien l'attendu # 999990609,00011,99999060900011,O,,NN,,,,true,1,,4,,PL,DE,LA,PYRAMIDE,92800,PUTEAUX,,,92062,,,,,,,,,,,,,,,,,,,1991-12-30,F,,,,,73.1Z,NAF1993,N # 999990625,00025,99999062500025,O,,NN,,,,true,1,,,,RTE,DE,MANOM,57100,THIONVILLE,,,57672,,,,,,,,,,,,,,,,,,,1995-11-30,F,,,,,27.3C,NAF1993,O # 999990666,00011,99999066600011,O,1986-05-15,,,,,false,4,,10,,RUE,CHAUCHAT,75009,PARIS,9,,,75109,,,,,,,,,,,,,,,,,,,1997-12-03,F,,,,,66.0A,NAF1993,N # 999990666,00029,99999066600029,O,1997-12-03,,,,,false,3,,2,,RUE,PILLET,WILL,75009,PARIS,9,,,75109,,,,,,,,,,,,,,,,,,,2000-07-01,F,,,,,66.0A,NAF1993,N # %% # sinon en version non enchainée, 2ème possibilité (avec étapes intermédiaires) etape_1 = cls.strip( string, search=r"\d{9};00[1-9]{3};.*", # suppression de tous les siren avec un NIC 00XXXX (en ne gardant plus que les NIC à 000XX) non_printable_char=False ) etape_2 = cls.strip( etape_1, search=b"\x3B", replace=b"\x2C", non_printable_char=False ) print( cls.strip( etape_2, search=r".*,(NAFRev\d*|NAP).*", # suppression de tous les NAF non définitifs ou les valeurs NAP qui semblent être incorrects non_printable_char=False ) ) # affiche bien l'attendu # 999990609,00011,99999060900011,O,,NN,,,,true,1,,4,,PL,DE,LA,PYRAMIDE,92800,PUTEAUX,,,92062,,,,,,,,,,,,,,,,,,,1991-12-30,F,,,,,73.1Z,NAF1993,N # 999990625,00025,99999062500025,O,,NN,,,,true,1,,,,RTE,DE,MANOM,57100,THIONVILLE,,,57672,,,,,,,,,,,,,,,,,,,1995-11-30,F,,,,,27.3C,NAF1993,O # 999990666,00011,99999066600011,O,1986-05-15,,,,,false,4,,10,,RUE,CHAUCHAT,75009,PARIS,9,,,75109,,,,,,,,,,,,,,,,,,,1997-12-03,F,,,,,66.0A,NAF1993,N # 999990666,00029,99999066600029,O,1997-12-03,,,,,false,3,,2,,RUE,PILLET,WILL,75009,PARIS,9,,,75109,,,,,,,,,,,,,,,,,,,2000-07-01,F,,,,,66.0A,NAF1993,N
Module data¶
Description générale
Module pour gérer tout ce qui se rapporte à la manipulation des données
-
corelibs.data.
append_files
(files_2_append, out_file_path, source_dir_path=None, skip_header=True, chunk=65536)¶ Description
Permet de concaténer des fichiers plats- Parameters
files_2_append – indique les fichiers à concaténer
out_file_path – indique le nom du fichier de sortie avec son chemin absolu
source_dir_path – indique le chemin absolu des fichiers sources (optionnel pour factoriser l’argument files_2_append)
skip_header –
indique s’il faut ou non écarter la ligne d’entête
valeurs possibles: False/Truevaleur par défaut: Truechunk –
indique le nombre de lignes à lire par cycle de lecture cf. DEFAULT_BUFFER_CHUNK_SIZE dans Installation & Mise à jour
valeurs possibles: entier/Nonevaleur par défaut: DEFAULT_BUFFER_CHUNK_SIZE
- Returns
- rien
Exemple :
# append_files.py # %% from corelibs import data, log, tools # %% # stress test sur un fichier des établissements d'open data gouv.fr # taille fichier : 29 928 195 lignes, pour un poids total de 4.88 Go # concaténation 3 fois le fichier originale @log.timing() @log.status_bar() def stress_test(): data.append_files( source_dir_path=r"D:\OneDrive\Desktop\StockEtablissement_utf8", # factorisation chemin fichiers sources files_2_append=( "StockEtablissement_utf8.csv", "StockEtablissement_utf8.tsv", "fichier_inexistant.toto", # => lève une erreur, sans action et continue... r"D:\OneDrive\Documents\_TEST_\StockEtablissement_utf8.csv" # fichier se trouvant à un autre emplacement ), out_file_path=r"D:\OneDrive\Documents\_TEST_\StockEtablissement_utf8_A3T.csv" ) stress_test() # Durée exécution : 00:04:10.60 # %% # Vérification poids fichier print(tools.get_file_properties(r"D:\OneDrive\Documents\_TEST_\StockEtablissement_utf8_A3T.csv")) # FileProperties(st_mode=33206, st_ino=3659174697355776, st_dev=3199390331, st_nlink=1, st_uid='miche', st_gid=0, st_size='14.65 Go', st_atime='20/01/2021 23:44:12', st_mtime='20/01/2021 23:44:12', st_ctime='20/01/2021 23:18:42') # %% # Vérification nb de lignes @log.timing() @log.status_bar() def stress_test(): print( tools.get_total_lines_in_file( r"D:\OneDrive\Documents\_TEST_\StockEtablissement_utf8_A3T.csv" ) ) stress_test() # Durée exécution : 00:02:40.59 pour lire et compter 89 784 581 de lignes # %% # %%time print(tools.get_fingerprint(r"D:\OneDrive\Documents\_TEST_\StockEtablissement_utf8_A3T.csv")) # 9ebe16404b9654fa790ed16ebcf5d4d6afd44ff62bb9a98a22533783dc0200f6 (2min 29s) # %% # nettoyage fichier, puisque la concaténation est faite sur des fichiers csv et tsv... @log.timing() @log.status_bar() def stress_test(): data.replace_in_file( path=r"D:\OneDrive\Documents\_TEST_\StockEtablissement_utf8_A3T.csv", pattern=b"\x09", # <=> tab replace=b"\x2C", # <=> , ignore_errors=True ) stress_test() # Durée exécution : 00:05:47.55 pour nettoyer 90 millions de lignes
-
corelibs.data.
has_same_header
(file_path, file_2_compare, separator=';')¶ Description
Permet de vérifier si 2 fichiers plats ont la même entête- Parameters
file_path – indique le fichier de référence avec son chemin absolu.
file_2_compare – indique le fichier à comparer avec son chemin absolu.
separator – indique le caractère séparateur.
- Returns
- tuple nommé avec comme attributs :
result (booléen)
cause (motif)
Exemple :
# has_same_header.py # %% from corelibs import data # %% # Test OK _ = data.has_same_header( r"C:\Users\miki\AppData\Local\Temp\tmpa1trgjyy_corelibs", r"C:\Users\miki\AppData\Local\Temp\tmpzhoxgdc2_corelibs" ) print(f"Résultat : {_.result}", f" - Infos : {_.cause}") # Résultat : True - Infos : {'hype': 'o(^ ^ o) Tout est OK, YEAH!!! (o ^ ^)o'} # %% # Test KO 1ère possibilité _ = data.has_same_header( r"C:\Users\miki\AppData\Local\Temp\tmpa1trgjyy_corelibs", r"C:\Users\miki\AppData\Local\Temp\tmpzhoxgdc2_corelibs" ) print(f"Résultat : {_.result}", f" - Infos : {_.cause}") # Résultat : False - Infos : { # 'cause': 'Différence format', # 'columns difference': ['owner', 'Created Time', 'Finger Print'], # 'file': [ # '#', # 'File Type', # 'File Name', # 'Technical ID', # 'owner', # 'Last Access', # 'Last Modification', # 'Created Time', # 'Bytes', # 'KiloBytes', # 'MegaBytes', # 'GigaBytes', # 'Finger Print' # ], # 'file 2 compare': [ # '#', # 'File Type', # 'File Name', # 'Technical ID', # 'Owner', # 'Last Access', # 'Last Modification', # 'OS Time', # 'Bytes', # 'KiloBytes', # 'MegaBytes', # 'GigaBytes', # 'Fingerprint' # ] # } # %% # Test KO 2ème possibilité _ = data.has_same_header( r"C:\Users\miki\AppData\Local\Temp\tmpa1trgjyy_corelibs", r"C:\Users\miki\AppData\Local\Temp\tmpzhoxgdc2_corelibs" ) print(f"Résultat : {_.result}", f" - Infos : {_.cause}") # Résultat : False - Infos : {'cause': 'Longueur différente', 'file': '14 colonnes', 'file 2 compare': '13 colonnes'}
-
corelibs.data.
head
(file_path, chunk=65536, skip_header=False, start_file=False, encoding='Latin-1', out_encoding='Latin-1')¶ Description
Permet d’extraire les premières lignes d’un gros fichier plat.- Parameters
file_path – indique l’emplacement en chemin absolu du fichier plat à traiter.
chunk – indique le nombre de lignes à extraire cf. DEFAULT_BUFFER_CHUNK_SIZE dans Installation & Mise à jour
skip_header –
indique si l’extraction doit écarter l’entête du fichier.
valeurs possibles: False/Truevaleur par défaut: Falsestart_file –
indique s’il faut lancer l’application liée par défaut au format du fichier, après extraction.
valeurs possibles: False/Truevaleur par défaut: Falseencoding – indique l’encodage à la lecture
out_encoding – indique l’encodage à l’écriture (identique à l’encoding de lecture par défaut)
- Returns
- le chemin du fichier extrait (à la même racine, avec le suffixe “_head_preview”)ouNone si problème
Exemple :
# head.py # %% from corelibs import data, log # stress test sur un fichier des établissements d'open data gouv.fr # taille fichier : 29 928 195 lignes, pour un poids total de 4.88 Go @log.timing() @log.status_bar() def stress_test(): return data.head(r"D:\OneDrive\Desktop\StockEtablissement_utf8\StockEtablissement_utf8.csv", start_file=True) preview_path = stress_test() # Durée exécution : 00:00:00.58 pour récupérer 65K/30 millions de lignes # %% # prévisualisation en mode web... data.preview(preview_path, separator=",")
-
corelibs.data.
preview
(obj, separator=';', allow_cell_edits=True, subprocess=True)¶ Description
Permet de visionner et manipuler rapidement les données extraites ou des données agrégées dans une application web.Warning
Attention aux erreurs de type Mémoire insuffisante. La manipulation des données sur l’application web devrait se faire sur un nombre restreint d’observations et spécialement en fonction des ressources propres au PC sur lequel est lancé les traitements python.- Parameters
obj – indique l’emplacement en chemin absolu du fichier plat ou le dataframe pandas à prévisualiser.
separator – indique le caractère séparateur.
allow_cell_edits –
indique la possibilité d’éditer les cellules lues.
valeurs possibles: False/Truevaleur par défaut: Truesubprocess –
indique si l’exécution se fait en mode threading ou non. Le comportement par défaut va tuer automatiquement le process si il n’est plus utilisé ou si l’exécution de la pile principale est finie (ce paramétrage fonctionne sous iPython, Jupyter & la console Python mais ne fontionne pas sur un terminal standard ou un terminal émulé - PyCharm par exemple - où il faudrait désactiver le threading)
valeurs possibles: False/Truevaleur par défaut: True
- Returns
- rien
Exemple :
# preview.py # %% import pandas as pd from corelibs import data # %% # prévisualisation standard à partir d'un fichier plat # %%time data.preview( r"D:\OneDrive\Desktop\StockEtablissement_utf8\StockEtablissement_utf8_tail_preview.tsv", separator="\t", ) # 32s pour lire et afficher 1 048 576 de lignes # 6min 27s pour lire et afficher 10 000 000 de lignes # %% # prévisualisation à partir d'un dataframe pandas # %%time df = pd.read_csv( r"D:\OneDrive\Desktop\StockEtablissement_utf8\StockEtablissement_utf8_tail_preview.tsv", sep="\t", dtype=str, engine="python", index_col=False ).fillna("") data.preview(df) # 1min 26s pour lire 1 048 576 de lignes
-
corelibs.data.
replace_in_file
(path, pattern, replace, regex_flag=None, out_file_path=None, ignore_errors=False, encoding='Latin-1', out_encoding='Latin-1')¶ Description
Permet de scanner un fichier et de remplacer tout son contenu.- Parameters
path – indique l’emplacement en chemin absolu du fichier plat à traiter.
pattern – indique la chaine de caractères ou le modèle regex à chercher.
replace – indique la chaine de caractères ou le modèle regex en remplacement.
regex_flag – indique les flags à utiliser. cf. Liens utiles, Librairie regex pour plus de détails
out_file_path – indique le fichier de sortie si nécessaire.
ignore_errors –
indique si l’ouverture des fichiers doit ignorer ou non les erreurs d’encodage de type “byte 0xff in position 0” qui survient lors d’un décodage caractère encodé en utf-16 alors que la lecture du fichier se fait avec le code utf-8.
valeurs possibles: False/Truevaleur par défaut: Falseencoding – indique l’encodage à la lecture
encoding – indique l’encodage à l’écriture (identique à l’encoding de lecture par défaut)
- Returns
- rien…
Exemple :
# replace_in_file.py # %% import re from corelibs import config, data, log # %% # contentu fichier source "termcolorlog_20201208_180401.LOG" avant # Tuesday 08 December 2020 - Ma log à moi que j'ai [termcolorlog.py:1] <> INFO : Bonjour, ceci est un test personnalisé niveau INFO # Tuesday 08 December 2020 - Ma log à moi que j'ai [termcolorlog.py:1] <> WARNING : Bonjour, ceci est un test personnalisé niveau WARNING # Tuesday 08 December 2020 - Ma log à moi que j'ai [termcolorlog.py:1] <> ERROR : Bonjour, ceci est un test personnalisé niveau ERROR # Tuesday 08 December 2020 - Ma log à moi que j'ai [termcolorlog.py:1] <> CRITICAL : Bonjour, ceci est un test personnalisé niveau CRITIQUE ####### # remplacement avec écrasement du fichier source data.replace_in_file( path=r"D:\OneDrive\Documents\_TEST_\__LOGS__\termcolorlog_20201208_180401.LOG", pattern="Bonjour,", replace="Au revoir !" ) # contenu fichier source "termcolorlog_20201208_180401.LOG" après # Tuesday 08 December 2020 - Ma log à moi que j'ai [termcolorlog.py:1] <> INFO : Au revoir ! ceci est un test personnalisé niveau INFO # Tuesday 08 December 2020 - Ma log à moi que j'ai [termcolorlog.py:1] <> WARNING : Au revoir ! ceci est un test personnalisé niveau WARNING # Tuesday 08 December 2020 - Ma log à moi que j'ai [termcolorlog.py:1] <> ERROR : Au revoir ! ceci est un test personnalisé niveau ERROR # Tuesday 08 December 2020 - Ma log à moi que j'ai [termcolorlog.py:1] <> CRITICAL : Au revoir ! ceci est un test personnalisé niveau CRITIQUE # %% # remplacement via modèle regex avec écrasement data.replace_in_file( path=r"D:\OneDrive\Documents\_TEST_\__LOGS__\termcolorlog_20201208_180401.LOG", pattern=r"^(Tuesday) (08) (December) (2020)(.*)(Au revoir !)(.*)$", replace=r"\4/12/\2\5Bonjour,\7 - modifié par regex =}" ) # contenu fichier source "termcolorlog_20201208_180401.LOG" après 2ème passage # 2020/12/08 - Ma log à moi que j'ai [termcolorlog.py:1] <> INFO : Bonjour, ceci est un test personnalisé niveau INFO - modifié par regex =} # 2020/12/08 - Ma log à moi que j'ai [termcolorlog.py:1] <> WARNING : Bonjour, ceci est un test personnalisé niveau WARNING - modifié par regex =} # 2020/12/08 - Ma log à moi que j'ai [termcolorlog.py:1] <> ERROR : Bonjour, ceci est un test personnalisé niveau ERROR - modifié par regex =} # 2020/12/08 - Ma log à moi que j'ai [termcolorlog.py:1] <> CRITICAL : Bonjour, ceci est un test personnalisé niveau CRITIQUE - modifié par regex =} # %% # remplacement avec redirection dans un autre fichier de sortie data.replace_in_file( path=r"D:\OneDrive\Documents\_TEST_\__LOGS__\termcolorlog_20201208_180401.LOG", pattern=r"^(.*)(INFO|WARNING|ERROR|CRITICAL)( : )(.*)$", replace=r"\4", out_file_path=r"D:\OneDrive\Documents\_TEST_\__LOGS__\Nouveau Fichier Nettoyé.TXT" ) # contenu fichier cible "Nouveau Fichier Nettoyé.TXT" après traitement # Bonjour, ceci est un test personnalisé niveau INFO - modifié par regex =} # Bonjour, ceci est un test personnalisé niveau WARNING - modifié par regex =} # Bonjour, ceci est un test personnalisé niveau ERROR - modifié par regex =} # Bonjour, ceci est un test personnalisé niveau CRITIQUE - modifié par regex =} # %% # utilisation flags regex data.replace_in_file( path=r"D:\OneDrive\Documents\_TEST_\__LOGS__\termcolorlog_20201208_180401.LOG", pattern=r"^(.*)(INFO|WARNING|ERROR|CRITICAL)( : )(.*)$", replace=r"\4", out_file_path=r"D:\OneDrive\Documents\_TEST_\__LOGS__\Nouveau Fichier Nettoyé Bis.TXT", regex_flag=re.M | re.I ) # création nouveau fichier "Nouveau Fichier Nettoyé Bis.TXT" traité # %% # remplacement fichier avec redirection dans un autre fichier, des espaces par des ; data.replace_in_file( path=r"D:\OneDrive\Documents\_TEST_\__LOGS__\termcolorlog_20201208_180401.LOG", pattern=b"\x20", replace=b"\x3B", out_file_path=r"D:\OneDrive\Documents\_TEST_\__LOGS__\Nouveau Fichier Nettoyé escape.TXT" ) # contenu fichier cible "Nouveau Fichier Nettoyé escape.TXT" après traitement # 2020/12/08;-;Ma;log;à;moi;que;j'ai;[termcolorlog.py:1];<>;;;;;;;;;;INFO;:;Au;revoir;!;ceci;est;un;test;personnalisé;niveau;INFO;-;modifié;par;regex;=} # 2020/12/08;-;Ma;log;à;moi;que;j'ai;[termcolorlog.py:1];<>;;;;;;;WARNING;:;Au;revoir;!;ceci;est;un;test;personnalisé;niveau;WARNING;-;modifié;par;regex;=} # 2020/12/08;-;Ma;log;à;moi;que;j'ai;[termcolorlog.py:1];<>;;;;;;;;;ERROR;:;Au;revoir;!;ceci;est;un;test;personnalisé;niveau;ERROR;-;modifié;par;regex;=} # 2020/12/08;-;Ma;log;à;moi;que;j'ai;[termcolorlog.py:1];<>;;;;;;CRITICAL;:;Au;revoir;!;ceci;est;un;test;personnalisé;niveau;CRITIQUE;-;modifié;par;regex;=} # %% config.DEFAULT_ENCODING_FILE = "utf-8" # écrasement du format par défaut en utf-8 comme demandé par open data # stress test sur un fichier des établissements d'open data gouv.fr # taille fichier : 29 928 195 lignes, pour un poids total de 4.88 Go # 10 dernière lignes du fichier original de 5244591168 octets <=> 4.88 Go # 999990583,00133,99999058300133,O,1993-01-01,NN,,,2006-11-25T22:25:28,false,4,CENTRALE DE MIJANES,,,,,09120,VARILHES,,,09324,,,,,,,,,,,,,,,,,,,2004-06-30,F,,,,,40.1A,NAFRev1,N # 999990583,00158,99999058300158,O,1998-09-07,NN,,,2019-11-14T14:00:51,true,3,PARC TECHNOL LA PARDIEU,6,,RUE,CONDORCET,63000,CLERMONT-FERRAND,,,63113,,,,,,,,,,,,,,,,,,,2004-06-30,F,,,,,28.4A,NAFRev1,N # 999990609,00011,99999060900011,O,,NN,,,,true,1,,4,,PL,DE LA PYRAMIDE,92800,PUTEAUX,,,92062,,,,,,,,,,,,,,,,,,,1991-12-30,F,,,,,73.1Z,NAF1993,N # 999990625,00025,99999062500025,O,,NN,,,,true,1,,,,RTE,DE MANOM,57100,THIONVILLE,,,57672,,,,,,,,,,,,,,,,,,,1995-11-30,F,,,,,27.3C,NAF1993,O # 999990641,00014,99999064100014,O,,NN,,,,true,1,,99,,BD,DE GRENELLE,75015,PARIS 15,,,75115,,,,,,,,,,,,,,,,,,,1986-06-15,F,,,,,65.01,NAP,N # 999990666,00011,99999066600011,O,1986-05-15,,,,,false,4,,10,,RUE,CHAUCHAT,75009,PARIS 9,,,75109,,,,,,,,,,,,,,,,,,,1997-12-03,F,,,,,66.0A,NAF1993,N # 999990666,00029,99999066600029,O,1997-12-03,,,,,false,3,,2,,RUE,PILLET WILL,75009,PARIS 9,,,75109,,,,,,,,,,,,,,,,,,,2000-07-01,F,,,,,66.0A,NAF1993,N # 999990666,00037,99999066600037,O,2000-07-01,NN,,,2020-05-20T03:34:55,true,3,8 A 10,8,,RUE,D'ASTORG,75008,PARIS 8,,,75108,,,,,,,,,,,,,,,,,,,2008-01-01,A,,,,,65.11Z,NAFRev2,N # 999990682,00034,99999068200034,O,2001-09-18,NN,,,,true,3,LE PONANT DE PARIS,27,,RUE,LEBLANC,75015,PARIS 15,,,75115,,,,,,,,,,,,,,,,,,,2003-12-18,F,,,,,65.2E,NAFRev1,N # 999992357,00015,99999235700015,O,2003-12-31,01,2017,,2019-06-24T14:13:19,true,5,,6,,RUE,DE L ETOILE,80090,AMIENS,,,80021,,,,,,,,,,,,,,,,,,,2012-01-22,A,,,,,81.10Z,NAFRev2,O @log.timing() @log.status_bar() def stress_test(): # sortie en fichier tabulé data.replace_in_file( path=r"D:\OneDrive\Desktop\StockEtablissement_utf8\StockEtablissement_utf8.csv", pattern=b"\x2C", # <=> , replace=b"\x09", # <=> tab out_file_path=r"D:\OneDrive\Desktop\StockEtablissement_utf8\StockEtablissement_utf8.tsv", ignore_errors=True ) stress_test() # Durée exécution : 00:01:32.17 # %% @log.timing() @log.status_bar() def stress_test(): # écrire sur le même fichier de sorti en tant que csv ; data.replace_in_file( path=r"D:\OneDrive\Desktop\StockEtablissement_utf8\StockEtablissement_utf8.tsv", pattern=b"\x09", # <=> tab replace=b"\x3B", # <=> ; ignore_errors=True ) stress_test() # Durée exécution : 00:01:20.13 # 10 dernière lignes du fichier TSV # 999990583;00133;99999058300133;O;1993-01-01;NN;;;2006-11-25T22:25:28;false;4;CENTRALE DE MIJANES;;;;;09120;VARILHES;;;09324;;;;;;;;;;;;;;;;;;;2004-06-30;F;;;;;40.1A;NAFRev1;N # 999990583;00158;99999058300158;O;1998-09-07;NN;;;2019-11-14T14:00:51;true;3;PARC TECHNOL LA PARDIEU;6;;RUE;CONDORCET;63000;CLERMONT-FERRAND;;;63113;;;;;;;;;;;;;;;;;;;2004-06-30;F;;;;;28.4A;NAFRev1;N # 999990609;00011;99999060900011;O;;NN;;;;true;1;;4;;PL;DE LA PYRAMIDE;92800;PUTEAUX;;;92062;;;;;;;;;;;;;;;;;;;1991-12-30;F;;;;;73.1Z;NAF1993;N # 999990625;00025;99999062500025;O;;NN;;;;true;1;;;;RTE;DE MANOM;57100;THIONVILLE;;;57672;;;;;;;;;;;;;;;;;;;1995-11-30;F;;;;;27.3C;NAF1993;O # 999990641;00014;99999064100014;O;;NN;;;;true;1;;99;;BD;DE GRENELLE;75015;PARIS 15;;;75115;;;;;;;;;;;;;;;;;;;1986-06-15;F;;;;;65.01;NAP;N # 999990666;00011;99999066600011;O;1986-05-15;;;;;false;4;;10;;RUE;CHAUCHAT;75009;PARIS 9;;;75109;;;;;;;;;;;;;;;;;;;1997-12-03;F;;;;;66.0A;NAF1993;N # 999990666;00029;99999066600029;O;1997-12-03;;;;;false;3;;2;;RUE;PILLET WILL;75009;PARIS 9;;;75109;;;;;;;;;;;;;;;;;;;2000-07-01;F;;;;;66.0A;NAF1993;N # 999990666;00037;99999066600037;O;2000-07-01;NN;;;2020-05-20T03:34:55;true;3;8 A 10;8;;RUE;D'ASTORG;75008;PARIS 8;;;75108;;;;;;;;;;;;;;;;;;;2008-01-01;A;;;;;65.11Z;NAFRev2;N # 999990682;00034;99999068200034;O;2001-09-18;NN;;;;true;3;LE PONANT DE PARIS;27;;RUE;LEBLANC;75015;PARIS 15;;;75115;;;;;;;;;;;;;;;;;;;2003-12-18;F;;;;;65.2E;NAFRev1;N # 999992357;00015;99999235700015;O;2003-12-31;01;2017;;2019-06-24T14:13:19;true;5;;6;;RUE;DE L ETOILE;80090;AMIENS;;;80021;;;;;;;;;;;;;;;;;;;2012-01-22;A;;;;;81.10Z;NAFRev2;O # %% @log.timing() @log.status_bar() def stress_test(): # remplacement dans le fichier csv nouvellement formé des dates ayant un format AAAA-MM-DD par DD/MM/AAAA uniquement # les champs datetime ayant le format AAAA-MM-DDTHH:MM:SS ne sont pas transformés data.replace_in_file( path=r"D:\OneDrive\Desktop\StockEtablissement_utf8\StockEtablissement_utf8.tsv", pattern=r"\b(\d{4})-(\d{2})-(\d{2})\b", replace=r"\3/\2/\1", ignore_errors=True ) stress_test() # Durée exécution : 00:05:50.94 # 10 dernière lignes du fichier TSV # 999990583;00133;99999058300133;O;01/01/1993;NN;;;2006-11-25T22:25:28;false;4;CENTRALE DE MIJANES;;;;;09120;VARILHES;;;09324;;;;;;;;;;;;;;;;;;;30/06/2004;F;;;;;40.1A;NAFRev1;N # 999990583;00158;99999058300158;O;07/09/1998;NN;;;2019-11-14T14:00:51;true;3;PARC TECHNOL LA PARDIEU;6;;RUE;CONDORCET;63000;CLERMONT-FERRAND;;;63113;;;;;;;;;;;;;;;;;;;30/06/2004;F;;;;;28.4A;NAFRev1;N # 999990609;00011;99999060900011;O;;NN;;;;true;1;;4;;PL;DE LA PYRAMIDE;92800;PUTEAUX;;;92062;;;;;;;;;;;;;;;;;;;30/12/1991;F;;;;;73.1Z;NAF1993;N # 999990625;00025;99999062500025;O;;NN;;;;true;1;;;;RTE;DE MANOM;57100;THIONVILLE;;;57672;;;;;;;;;;;;;;;;;;;30/11/1995;F;;;;;27.3C;NAF1993;O # 999990641;00014;99999064100014;O;;NN;;;;true;1;;99;;BD;DE GRENELLE;75015;PARIS 15;;;75115;;;;;;;;;;;;;;;;;;;15/06/1986;F;;;;;65.01;NAP;N # 999990666;00011;99999066600011;O;15/05/1986;;;;;false;4;;10;;RUE;CHAUCHAT;75009;PARIS 9;;;75109;;;;;;;;;;;;;;;;;;;03/12/1997;F;;;;;66.0A;NAF1993;N # 999990666;00029;99999066600029;O;03/12/1997;;;;;false;3;;2;;RUE;PILLET WILL;75009;PARIS 9;;;75109;;;;;;;;;;;;;;;;;;;01/07/2000;F;;;;;66.0A;NAF1993;N # 999990666;00037;99999066600037;O;01/07/2000;NN;;;2020-05-20T03:34:55;true;3;8 A 10;8;;RUE;D'ASTORG;75008;PARIS 8;;;75108;;;;;;;;;;;;;;;;;;;01/01/2008;A;;;;;65.11Z;NAFRev2;N # 999990682;00034;99999068200034;O;18/09/2001;NN;;;;true;3;LE PONANT DE PARIS;27;;RUE;LEBLANC;75015;PARIS 15;;;75115;;;;;;;;;;;;;;;;;;;18/12/2003;F;;;;;65.2E;NAFRev1;N # 999992357;00015;99999235700015;O;31/12/2003;01;2017;;2019-06-24T14:13:19;true;5;;6;;RUE;DE L ETOILE;80090;AMIENS;;;80021;;;;;;;;;;;;;;;;;;;22/01/2012;A;;;;;81.10Z;NAFRev2;O # %% # Pour changer le champs datetime ayant le format AAAA-MM-DDTHH:MM:SS il faut chaîner avec une nouvelle expression régulière @log.timing() @log.status_bar() def stress_test(): # remplacement les champs datetime ayant le format AAAA-MM-DDTHH:MM:SS ne sont pas transformés par DD/MM/AAAA HH:MM data.replace_in_file( path=r"D:\OneDrive\Desktop\StockEtablissement_utf8\StockEtablissement_utf8.tsv", pattern=r"\b(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\b", replace=r"\3/\2/\1 \4:\5", ignore_errors=True ) stress_test() # Durée exécution : 00:05:00.71 # 10 dernière lignes du fichier TSV # 999990583;00133;99999058300133;O;01/01/1993;NN;;;25/11/2006 22:25;false;4;CENTRALE DE MIJANES;;;;;09120;VARILHES;;;09324;;;;;;;;;;;;;;;;;;;30/06/2004;F;;;;;40.1A;NAFRev1;N # 999990583;00158;99999058300158;O;07/09/1998;NN;;;14/11/2019 14:00;true;3;PARC TECHNOL LA PARDIEU;6;;RUE;CONDORCET;63000;CLERMONT-FERRAND;;;63113;;;;;;;;;;;;;;;;;;;30/06/2004;F;;;;;28.4A;NAFRev1;N # 999990609;00011;99999060900011;O;;NN;;;;true;1;;4;;PL;DE LA PYRAMIDE;92800;PUTEAUX;;;92062;;;;;;;;;;;;;;;;;;;30/12/1991;F;;;;;73.1Z;NAF1993;N # 999990625;00025;99999062500025;O;;NN;;;;true;1;;;;RTE;DE MANOM;57100;THIONVILLE;;;57672;;;;;;;;;;;;;;;;;;;30/11/1995;F;;;;;27.3C;NAF1993;O # 999990641;00014;99999064100014;O;;NN;;;;true;1;;99;;BD;DE GRENELLE;75015;PARIS 15;;;75115;;;;;;;;;;;;;;;;;;;15/06/1986;F;;;;;65.01;NAP;N # 999990666;00011;99999066600011;O;15/05/1986;;;;;false;4;;10;;RUE;CHAUCHAT;75009;PARIS 9;;;75109;;;;;;;;;;;;;;;;;;;03/12/1997;F;;;;;66.0A;NAF1993;N # 999990666;00029;99999066600029;O;03/12/1997;;;;;false;3;;2;;RUE;PILLET WILL;75009;PARIS 9;;;75109;;;;;;;;;;;;;;;;;;;01/07/2000;F;;;;;66.0A;NAF1993;N # 999990666;00037;99999066600037;O;01/07/2000;NN;;;20/05/2020 03:34;true;3;8 A 10;8;;RUE;D'ASTORG;75008;PARIS 8;;;75108;;;;;;;;;;;;;;;;;;;01/01/2008;A;;;;;65.11Z;NAFRev2;N # 999990682;00034;99999068200034;O;18/09/2001;NN;;;;true;3;LE PONANT DE PARIS;27;;RUE;LEBLANC;75015;PARIS 15;;;75115;;;;;;;;;;;;;;;;;;;18/12/2003;F;;;;;65.2E;NAFRev1;N # 999992357;00015;99999235700015;O;31/12/2003;01;2017;;24/06/2019 14:13;true;5;;6;;RUE;DE L ETOILE;80090;AMIENS;;;80021;;;;;;;;;;;;;;;;;;;22/01/2012;A;;;;;81.10Z;NAFRev2;O
-
corelibs.data.
split_file
(file_path, skip_header=False, start=None, chunk=65536, suffix='_part_')¶ Description
Permet de scinder un fichier plat volumineux en plusieurs petits fichiers- Parameters
file_path – indique l’emplacement en chemin absolu du fichier plat à scinder.
skip_header –
indique s’il faut ou non écarter la ligne d’entête.
valeurs possibles: False/Truevaleur par défaut: Falsestart – indique si besoin, la première ligne à partir de laquelle l’extraction va démarrer
chunk –
indique le nombre de lignes à scinder par fichier cf. DEFAULT_BUFFER_CHUNK_SIZE dans Installation & Mise à jour. Utilisé conjointement avec start cet argument sera pris comme l’offset d’arrêt pour extraire le fichier
valeurs possibles: entier/Nonevaleur par défaut: DEFAULT_BUFFER_CHUNK_SIZEsuffix – indique le suffix à appliquer aux fichiers scindés
- Returns
- rien
Exemple :
# split_file.py # %% import pandas as pd from corelibs import data, log, tools # %% # stress test sur un fichier des établissements d'open data gouv.fr # taille fichier : 29 928 195 lignes, pour un poids total de 4.88 Go # découpage par tranche de 10 millions de lignes avec les entêtes (par défaut) @log.timing() @log.status_bar() def stress_test(): data.split_file(r"D:\OneDrive\Desktop\StockEtablissement_utf8\StockEtablissement_utf8.tsv", chunk=10000000) stress_test() # Durée exécution : 00:02:02.60 # %% # %%time # vérifications par scan modèles wcl = tools.get_total_lines_in_folder( dir_2_scan=r"D:\OneDrive\Desktop\StockEtablissement_utf8", files_pattern="*_part_*.tsv" ) print(wcl) # Wcl(total_files=3, total_lines=29928199) - Durée exécution : 12.2s # il y a un delta de 6 lignes avec la comparaison via pandas ci-dessous (ce delta est normal) # %% # vérifications entêtes for i in range(3): data.head( r"D:\OneDrive\Desktop\StockEtablissement_utf8\StockEtablissement_utf8_part_{i}.tsv".format(i=i), chunk=10, start_file=True ) # %% # vérification pandas @log.timing() @log.status_bar() def verif_pandas(): for i in range(3): df = pd.read_csv( r"D:\OneDrive\Desktop\StockEtablissement_utf8\StockEtablissement_utf8_part_{i}.tsv".format(i=i), sep="\t", dtype=str, usecols=["siren"], engine="python" ) print(f"total lignes {i}", len(df)) del df verif_pandas() # Durée exécution : 00:28:23.79 # total lignes 0 10000000 # total lignes 1 10000000 # total lignes 2 9928193 # %% # découpage par tranche de 10 millions de lignes sans les entêtes @log.timing() @log.status_bar() def stress_test(): data.split_file( r"D:\OneDrive\Desktop\StockEtablissement_utf8\StockEtablissement_utf8.tsv", chunk=10000000, skip_header=True ) stress_test() # Durée exécution : 00:02:25.85 # %% # %%time # découpage arbitraire, à partir d'une position pour un nombre de lignes données data.split_file( r"D:\OneDrive\Desktop\StockEtablissement_utf8\StockEtablissement_utf8.tsv", start=10000000, chunk=100, suffix="_xtr_" ) # Durée exécution 1min
-
corelibs.data.
tail
(file_path, chunk=65536, skip_header=False, start_file=False, encoding='Latin-1', out_encoding='Latin-1')¶ Description
Permet d’extraire les dernières lignes d’un gros fichier plat.- Parameters
file_path – indique l’emplacement en chemin absolu du fichier plat à traiter.
chunk – indique le nombre de lignes à extraire cf. DEFAULT_BUFFER_CHUNK_SIZE dans Installation & Mise à jour
skip_header –
indique si l’extraction doit écarter l’entête du fichier.
valeurs possibles: False/Truevaleur par défaut: Falsestart_file –
indique s’il faut lancer l’application liée par défaut au format du fichier, après extraction.
valeurs possibles: False/Truevaleur par défaut: Falseencoding – indique l’encodage à la lecture
out_encoding – indique l’encodage à l’écriture (identique à l’encoding de lecture par défaut)
- Returns
- le chemin du fichier extrait (à la même racine, avec le suffixe “_tail_preview”)
Exemple :
# tail.py # %% from corelibs import data, log # stress test sur un fichier des établissements d'open data gouv.fr # taille fichier : 29 928 195 lignes, pour un poids total de 4.88 Go @log.timing() @log.status_bar() def stress_test(): return data.tail( r"D:\OneDrive\Desktop\StockEtablissement_utf8\StockEtablissement_utf8.tsv", chunk=1048576 # Excel > 2007 ) preview_path = stress_test() # Durée exécution : 00:00:03.23 pour extraire 1048576 de lignes sur les 30 millions de lignes du fichier sources
Module tools¶
Description générale
Module pour gérer les compressions, diagnostics, calcul des tailles occupées, sécuriser les données etc.
-
corelibs.tools.
cipher
(obj, password, delete_source_file=True)¶ Description
Permet de chiffrer une chaîne de caractère ou un fichierWarning
Ce chiffrement est adapté pour protéger des fichiers plats contenant du code ou partie de codes sensibles, ou un fichier de petite taille.Le mot de passe tient compte de la casse.- Parameters
obj – indique la chaine de caractère ou le chemin absolu du fichier à chiffrer
password – indique le mot de passe à appliquer lors du chiffrement
delete_source_file –
indique si le fichier source doit être supprimé après le chiffrement
valeurs possibles: False/Truevaleur par défaut: True
- Returns
- Trueouchaîne chiffrée (si obj est une chaîne de caractère)
Exemple :
# cipher.py # %% from corelibs import tools cle_secrete = "Clé secrète de la morkitu! • 28Nov2013KT" # %% # chiffrement chaine de caractères message = """ import corelibs dict = {"msg": "Hello Kim", "from": "papa"} print("message encapsulé chiffré", "•"*31, dict, dict["msg"], corelibs) corelibs.lazy.merge_dictionaries(dict, {"from": "papa ❤ =}"}) """ message_chiffre = tools.cipher(message, cle_secrete) print(message_chiffre) # affiche le binaire suivant # b'x\xda\x1d\xc1k\xb3B@\x00\x00\xd0_\xd4\x8c\xc7\xb6\xf4Q\x96\xc8s\xc3j}1j\xf3\x0c[\xa4\xf8\xf5w\xe6\x9e\xd3\x11H\xe9 # \x1a\xf2B^[\xd2\xab`/:v[i\xc7\xfa\xa5k\xffN\x9a\xe7\xf5\x1c\x8eF\x8ca\rygH\xcf\xeb\xb2\x9b\x0e\xef\xf1\xeb"\xeew;U # \x16\xc06\x98\xc2\xfeJ\xb2\xdfY\xaemu\x8aZL\x16U\xb6H\xcb\x16\x81IL\xc9\xe9\xef\xc3\x15\xf7\xed\xc4~"R\xd39$\xd5\x92 # \xa5j|/\xa5\xa1>\x0b\x10m\xac\x8d\x18*(\x1f\xb0\xe3Z\x82(\x9a\xa5\x05f\x1b\xb0\x8b\x0e2\x06\xcbtRB\xd0\x9c"\xdex\xda. # \xd9?\xbe\xa8#\xe64\xadh\x9e\x0f\x83\x96OpX\xd7\xb2\x07\x85\\>nR\x83\xa5\xd3\xc9\xafW\x9a\xe6\xa6b]\x9a1\xd1W-\x86\xe6 # \x83\xf7\x98\xf6r\xf6Z\x19\xf3j/\xe7\xe0H\xa2\x98\\}\x0c`E\x140\xe2\xa6\x15P1\xc8\xe0\xc6\xaa0\xe0\xf3R$\xa3\xad\xc7 # m&\xd9x\x94\x04\x1a\xddC\x8b\xebN\xea"\xa5\x1a\xc3\\4\xdfKl\x14\xb7\xef>\x82\x8b\xfa\xc6;oN\xf0V\x9dq\xaf\x0f\x98l # \xf1\xf0L\xca\x80er0YA\x80\x8c\xe4\xf79:\x8b\x81^n\x8e\x94\xc8\xf0\xda?\xb9,}\xc7' # %% # chiffrement fichier hello.py ayant comme contenu : # import sys # # sys.path.append(r"D:\OneDrive\Documents\[PYTHON_PROJECTS]\corelibs") # # import corelibs # # dict = {"msg": "Hello Kim", "from": "papa"} # print("message encapsulé chiffré", "•"*31, dict, dict["msg"], corelibs) # # corelibs.lazy.merge_dictionaries(dict, {"from": "papa ❤ =}"}) tools.cipher(r"D:\OneDrive\Documents\_TEST_\Chiffrements\hello.py", cle_secrete) # résultat fichier binaire hello.py.clk # 78da 1dc1 d7b2 4340 0000 d02f 32a3 2578 # d4a2 5bbb ba17 838d 1021 ca92 c8d7 df99 # 7b8e 248d 549c 5626 57fe 185a 7cda 4495 # 9e40 9695 6e51 e57f 86ec a79d 6467 218c # edbc a60f 1435 8cb3 3fb9 a00a f5fc 9bc7 # db39 8aa2 d57c b6f3 048f c37b 247b 4aa6 # caaf 2395 f5ea 6860 f05a 7cb2 340d e201 # 91bd 2ec3 0dc4 fac8 8869 feba 6514 adcd # eb1b 6a32 d117 804f 4e85 7a85 55f2 3528 # 67be 7b2d 6865 0e99 a477 3f38 4d0a dd36 # 33c2 ac0d 9f2f a4f7 5bb3 9892 aeba 46ef # 8463 d374 f629 988e f8f0 8b67 3c13 e4be # 32a3 5751 0d0b adf6 224f 99dd eb56 7a74 # b8fa b627 16e7 ea76 dc46 e8a3 93c6 1b5f # 840f c752 5f7e b107 0ebf beee da06 58c4 # 29f0 80f5 e03c 0ac1 d2af b842 c58e 2e7d # 27a7 1cbf 2b9e 2318 7cce 2a31 389c 5037 # 0719 013e b392 66d1 0f84 27d6 9312 4ac1 # c3f4 a0ac 6953 41e3 f6e5 c5ce 220c e331 # 58f9 1249 46df abbf 1b63 3db9 9a2f e470 # d835 e31b 4c65 d802 fffd 4bbe 356d e5ec # e74e 0667 ab58 dfcc fc7e 9d93 df8f 7c38 # 4bde bb49 a305 0c47 1c04 b895 3621 72cc # ea92 2c3a 7f0f 07dd 0b02 b7ed 6f2f 5abc # 4001 d516 0876 a296 62d8 81e5 d298 8a30 # 0f50 974f a7dc 9db2 bd45 cd1f c744 a9e7
-
corelibs.tools.
decipher
(obj, password, delete_source_file=True)¶ Description
Permet de déchiffrer une chaîne de caractère ou un fichierWarning
Le mot de passe tient compte de la casse.- Parameters
obj – indique la chaine de caractère ou le chemin absolu du fichier à déchiffrer
password – indique le mot de passe à appliquer lors du déchiffrement
delete_source_file –
indique si le fichier source doit être supprimé après le déchiffrement
valeurs possibles: False/Truevaleur par défaut: True
- Returns
- Trueouchaîne déchiffrée (si obj est une chaîne binaire)
Exemple :
# decipher.py # %% from corelibs import tools, lazy as lz cle_secrete = "Clé secrète de la morkitu! • 28Nov2013KT" # %% # déchiffrement chaine de caractères message = """ import corelibs dict = {"msg": "Hello Kim", "from": "papa"} print("message encapsulé chiffré", "•"*31, dict, dict["msg"], corelibs) corelibs.lazy.merge_dictionaries(dict, {"from": "papa ❤ =}"}) """ message_chiffre = tools.cipher(message, cle_secrete) message_dechiffre = tools.decipher(message_chiffre, cle_secrete) print(message_dechiffre) # affiche # import corelibs # # dict = {"msg": "Hello Kim", "from": "papa"} # print("message encapsulé chiffré", "•"*31, dict, dict["msg"], corelibs) # # corelibs.lazy.merge_dictionaries(dict, {"from": "papa ❤ =}"}) # %% # exécution dynamique de la chaîne déchiffrée exec(message_dechiffre) # affichera le print chiffré => message encapsulé chiffré ••••••••••••••••••••••••••••••• {'msg': 'Hello Kim', 'from': 'papa'} Hello Kim <module 'corelibs' from 'D:\\OneDrive\\Documents\\[PYTHON_PROJECTS]\\corelibs\\corelibs\\__init__.py'> print("dictionnaire défini dans la chaine déchiffrée : ", dict) # dictionnaire défini dans la chaine déchiffrée : {'msg': 'Hello Kim', 'from': 'papa ❤ =}'} # note : # le dictionnaire initiale est {"msg": "Hello Kim", "from": "papa"} # mais la valeur a été écrasée par l'instruction corelibs.lazy.merge_dictionaries(dict, {"from": "papa ❤ =}"}) # ce qui donne bien # dictionnaire défini dans la chaine déchiffrée : {'msg': 'Hello Kim', 'from': 'papa ❤ =}'} # %% # déchiffrement fichier .clk tools.decipher(r"D:\OneDrive\Documents\_TEST_\Chiffrements\hello.py.clk", cle_secrete) # %% # exécution du fichier déchiffré 1ère version lz.add_dir_path_2_project(r"D:\OneDrive\Documents\_TEST_\Chiffrements") import hello # charge le module hello.py déchiffré print("*"*31, hello.dict) # affichera ******************************* {'msg': 'Hello Kim', 'from': 'papa ❤ =}'} # %% # ou si les chemins sont bien définis, 2ème version exec(open(r"D:\OneDrive\Documents\_TEST_\Chiffrements\hello.py", encoding="utf-8").read()) import hello as lo # charge le module hello.py déchiffré print("•"*31, lo.dict) # affichera ••••••••••••••••••••••••••••••• {'msg': 'Hello Kim', 'from': 'papa ❤ =}'} # attention, la 2ème version fonctionne car dans le programme hello.py, il y a une instruction sys.path.append(...)
-
corelibs.tools.
get_file_properties
(file_path, pretty_byte_size=True, ignore_errors=False)¶ Description
Récupère les informations d’un fichier ou d’un répertoire- Parameters
file_path – chemin absolu du fichier/répertoire
pretty_byte_size –
afficher la taille du fichier/répertoire de manière lisible pour un humain
valeurs possibles: False/Truevaleur par défaut: Trueignore_errors –
forcer l’exécution lorsqu’une erreur est levée
valeurs possibles: False/Truevaleur par défaut: False (cf. DEFAULT_IGNORE_ERROR dans Installation & Mise à jour)
- Returns
- tuple nommé avec comme attributs :
st_mode (mode de protection en binaire)
st_ino (n° inode)
st_dev (n° machine)
st_nlink (nb de liens)
st_uid (propriétaire)
st_gid (groupe id sous Windows ou groupe sous Unix)
st_size (taille du fichier/répertoire)
st_atime (date dernier accès)
st_mtime (date dernière modification)
st_ctime (date de création sous Windows et date dernier modif/accès sous Unix)
Exemple :
# get_file_properties.py # %% from corelibs import tools as to # %% # récupération des informations par défaut (affichange la taille dynamiquement, à la valeur la plus appropriée) filename = r"D:\OneDrive\Documents\_TEST_\2020-11-11.jpg" filename_properties = to.get_file_properties(filename) print(filename_properties) # affiche l'objet FileProperties( # st_mode=33206, # st_ino=11540474045256220, # st_dev=3199390331, # st_nlink=1, # st_uid='Invités', # st_gid=0, # st_size='96.26 Ko', # la taille est exprimée en Ko pour une petite image # st_atime='13/11/2020 22:22:21', # st_mtime='11/11/2020 22:10:46', # st_ctime='11/11/2020 22:10:39') # %% # récupération des informations par défaut (affichange la taille dynamiquement, à la valeur la plus appropriée) filename = r"D:\OneDrive\Documents\_TEST_\Zatoichi.avi" filename_properties = to.get_file_properties(filename) print(filename_properties) # affiche l'objet FileProperties( # st_mode=33206, # st_ino=1125899906961926, # st_dev=3199390331, # st_nlink=1, st_uid='miche', # st_gid=0, # st_size='699.78 Mo', # la taille est exprimée en Mo pour le film Zatoichi.avi # st_atime='13/11/2020 22:19:27', # st_mtime='22/03/2013 20:17:02', # st_ctime='10/11/2020 15:56:52') # %% # récupération des informations avec la taille ventilée par unité de mesure (jusqu'au To) # fichier plus gros filename = r"D:\OneDrive\Documents\_TEST_\Zatoichi.avi" filename_properties = to.get_file_properties(filename, pretty_byte_size=False) print(filename_properties) # affiche l'objet FileProperties( # st_mode=33206, # st_ino=1125899906961926, # st_dev=3199390331, # st_nlink=1, # st_uid='miche', # st_gid=0, # st_size=ByteSize( # objet ByteSize contenant toutes les tailles converties depuis le nb d'octets # byte=733775872, # kilobyte=716578.0, # megabyte=699.78, # gigabyte=0.68, # terabyte=0.0), # st_atime='13/11/2020 22:19:27', # st_mtime='22/03/2013 20:17:02', # st_ctime='10/11/2020 15:56:52') # pour accéder à la taille en gigaoctet (gigabyte) par exemple récupérer directement son attribut print( "La faille en Go du fichier Zatoichi.avi est de {taille} Go" .format(taille=filename_properties.st_size.gigabyte) ) # affichera "La faille en Go du fichier Zatoichi.avi est de 0.68 Go" # %% # récupération des informations par défaut (affichange la taille dynamiquement, à la valeur la plus appropriée) filename = r"D:\OneDrive\Documents\_TEST_" filename_properties = to.get_file_properties(filename) print(filename_properties) # affiche l'objet FileProperties( # st_mode=16895, # st_ino=281474976804077, # st_dev=3199390331, # st_nlink=1, # st_uid='miche', # st_gid=0, # st_size='4.12 Go', # la taille est exprimée en Go pour le répertoire _TEST_ # st_atime='14/11/2020 18:23:11', # st_mtime='14/11/2020 17:58:08', # st_ctime='07/10/2020 22:17:12')
-
corelibs.tools.
get_fingerprint
(obj, algorithm='sha256', eval_as_string=False, chunk=67108864, ignore_errors=False)¶ Description
Calculer l’empreinte digitale (signature numérique) d’une chaîne de caractères ou d’un fichier passé en argument- Parameters
obj –
chaîne de caractèresouchemin absolu du fichieralgorithm –
applique l’algorithme de hashage
valeurs possibles: ‘blake2b’, ‘blake2s’, ‘md5’, ‘sha1’, ‘sha224’, ‘sha256’, ‘sha384’, ‘sha512’, ‘sha3_256’, ‘sha3_224’, ‘sha3_384’ ou ‘sha3_512’valeur par défaut: sha256eval_as_string –
permet de forcer l’évaluation comme étant une chaine de caractère (si l’objet passé en argument a un nom contenant des caractères \ ou / et n’est pas en réalité un chemin de fichiers)
valeurs possibles: False/Truevaleur par défaut: Falsechunk –
indique le buffer de lecture.
valeur par défaut: DEFAULT_BYTE_CHUNK_SIZE (cf. Installation & Mise à jour)ignore_errors –
forcer l’exécution lorsqu’une erreur est levée
valeurs possibles: False/Truevaleur par défaut: False (cf. DEFAULT_IGNORE_ERROR dans Installation & Mise à jour)
- Returns
empreinte digital unique
Exemple :
# get_fingerprint.py # %% from corelibs import tools as to, log # %% # Même empreinte = Même fichier (quelque soit son nom, sa date de modif, propriétaire etc...) # fichier 1 filename = r"D:\OneDrive\Documents\_TEST_\2020-11-11.jpg" print(to.get_file_properties(filename)) # FileProperties(st_mode=33206, st_ino=11540474045256220, st_dev=3199390331, st_nlink=1, st_uid='Invités', st_gid=0, st_size='96.26 Ko', st_atime='14/11/2020 22:12:45', st_mtime='11/11/2020 22:10:46', st_ctime='11/11/2020 22:10:39') print(to.get_fingerprint(filename)) # b6bbd28aebe109adda9bc16a8f838a5043d7980968a37a5d48f890f7fb4d89dc # %% # fichier 1 copié et les propriétés affichent bien une différence copy_filename = r"D:\OneDrive\Documents\_TEST_\2020-11-11 - Copie.jpg" print(to.get_file_properties(copy_filename)) # FileProperties(st_mode=33206, st_ino=19984723346576074, st_dev=3199390331, st_nlink=1, st_uid='miche', st_gid=0, st_size='96.26 Ko', st_atime='14/11/2020 22:06:59', st_mtime='11/11/2020 22:10:46', st_ctime='14/11/2020 21:56:29') print(to.get_fingerprint(copy_filename)) # b6bbd28aebe109adda9bc16a8f838a5043d7980968a37a5d48f890f7fb4d89dc # %% # algorithme disponible pour le hashage print(to.get_fingerprint(filename, algorithm="blake2b")) # 0a0ba79c2e6535b256c110bf823ea21b32fa7d1fdbeb16374ec3437269ad1f01e4dfb6a72b0dab929807737a331ac6a8988ebb6943d4ef10e5650128f4ac0ef0 print(to.get_fingerprint(filename, algorithm="blake2s")) # 0c6b739b821f0fb560e5545445e3a4c600ffc171e506ff307be0528f9d274b56 print(to.get_fingerprint(filename, algorithm="md5")) # 62383435cc0519bad598cc51783c5d47 print(to.get_fingerprint(filename, algorithm="sha1")) # f50a38a0c0952f96ae98aa54da7929bfb463f8dd print(to.get_fingerprint(filename, algorithm="sha224")) # c176d2d98a4f8563762ce3863efb942dbb9c496b4bee89a0374e42fa print(to.get_fingerprint(filename, algorithm="sha256")) # b6bbd28aebe109adda9bc16a8f838a5043d7980968a37a5d48f890f7fb4d89dc print(to.get_fingerprint(filename, algorithm="sha384")) # c839a0c58ef1ba3a7577de093f3d0e3746600b7b28fa08881f62aa7d4871220b9373ebdc620704e84c965d972cf887fb print(to.get_fingerprint(filename, algorithm="sha512")) # 39e72a89e167aa86f998e61763b0b43619cb6347118dd5f6713f830688b7e16cc8b006e8027a3bf1b0c260d24a76a13e7e233c3ab179f4e76865215a1d4007a4 print(to.get_fingerprint(filename, algorithm="sha3_256")) # e0009df152ee03665a3f26bc434d143873f2abc900e85e4e45d85608d6fd1787 print(to.get_fingerprint(filename, algorithm="sha3_224")) # 0f6ab25b4406ed8f98decae73375451286166d2e3d01095c15530069 print(to.get_fingerprint(filename, algorithm="sha3_384")) # 3d3d00f27d1663273d80cd9d4f1f55cf2f185d12f7c4387a77e91daae5ff179ecf8692c975b2f86b92010de5202ce32a print(to.get_fingerprint(filename, algorithm="sha3_512")) # ec208132962c717b6f92105ff04a2af93e2195fca22babc17b2b5ddb784b05c913b86cf09dd37e4ec699e342056051f61f400f290e7b8d5f4e8756d08d6e87ff # %% # Empreinte d'une chaine de caractère str_2_hash = "Hello Kim!" print( "L'empreinte SH256 de \"{str_2_hash}\" est \"{str_hashed}\"" .format( str_2_hash=str_2_hash, str_hashed=to.get_fingerprint(str_2_hash) ) ) # L'empreinte SH256 de "Hello Kim!" est "8c9affc6a8329ea9c8a87cfe989565c21b24136dc57ccf9407aeefbcac87f97a" # %% str_2_hash = "/!\\ ATTENTION /!\\" # doit être forcé comme chaine de caractères pour l'évaluation car contient des caractères \ et / print( "L'empreinte SH256 de \"{str_2_hash}\" est \"{str_hashed}\"" .format( str_2_hash=str_2_hash, str_hashed=to.get_fingerprint(str_2_hash, eval_as_string=True) ) ) # L'empreinte SH256 de "/!\ ATTENTION /!\" est "20f2328fcc5d513e330f5badadac2c0bd2685d8a21ce49daf7690cc6e783ff65" # %% # stress test sur un fichier des établissements d'open data gouv.fr # taille fichier : 29 928 195 lignes, pour un poids total de 4.88 Go @log.timing() @log.status_bar() def stress_test(): str_2_hash = r"D:\OneDrive\Desktop\StockEtablissement_utf8\StockEtablissement_utf8.csv" print( "L'empreinte SH256 de \"{str_2_hash}\" est \"{str_hashed}\"" .format( str_2_hash=str_2_hash, str_hashed=to.get_fingerprint(str_2_hash) ) ) stress_test() # Durée exécution : 00:00:12.07 # L'empreinte SH256 de "D:\OneDrive\Desktop\StockEtablissement_utf8\StockEtablissement_utf8.csv" est "072c0f2dc85bd326197318546da4331e6c900c39302145fc7013532aaedf4af8"
-
corelibs.tools.
get_total_lines_in_file
(file, chunk=67108864)¶ Description
Permet de compter le nombre de lignes dans un fichier plat- Parameters
file – indique l’emplacement du fichier avec son chemin absolu
chunk –
indique le buffer de lecture.
valeur par défaut: DEFAULT_BYTE_CHUNK_SIZE (cf. Installation & Mise à jour)
- Returns
- total lignes lues
Exemple :
# get_total_lines_in_file.py from corelibs import tools as to, log print( "Total lignes lues :", to.get_total_lines_in_file(r"\\wsl$\Ubuntu-20.04\root\.zsh_history") ) # affiche Total lignes lues : 46 print( "Total lignes lues :", to.get_total_lines_in_file(r"D:\OneDrive\Documents\_TEST_\SAS\Librairie_SAS\00_LIB_Macros_Communes.sas") ) # affiche Total lignes lues : 4060 # stress test sur un fichier des établissements d'open data gouv.fr # taille fichier : 29 928 195 lignes, pour un poids total de 4.88 Go @log.timing() @log.status_bar() def stress_test(): print( "Total lignes lues :", to.get_total_lines_in_file(r"D:\OneDrive\Desktop\StockEtablissement_utf8\StockEtablissement_utf8.tsv") ) stress_test() # Durée exécution : 00:00:12.07 # Total lignes lues : 29928195
-
corelibs.tools.
get_total_lines_in_folder
(dir_2_scan, files_pattern, to_exclude=None)¶ Description
Permet de compter le total de nombres de lignes de tous les fichiers plats dans un dossier, avec possibilités de filtrage- Parameters
dir_2_scan – indique l’emplacement du répertoire à scanner en chemin absolu
files_pattern – indique le schéma du scan.
to_exclude – indique les exclusions, qu’elles soient des sous dossiers et/ou des fichiers. Les exclusions peuvent être des schémas d’exclusions.
- Returns
- tuple nommé avec comme attributs :
total_files (total de fichiers lus)
total_lines (total de lignes lues)
Exemple :
# get_total_lines_in_folder.py # %% from corelibs import tools as to # %% # Scan standard... wcl = to.get_total_lines_in_folder(r"\\wsl$\Ubuntu-20.04\root", "*history") print(wcl) # affiche un objet Wcl(total_files=3, total_lines=431) # %% ######################################################################################################################## # Scan avec multiple schéma et exclusion répertoires et/ou fichiers # étalon *.sas wcl = to.get_total_lines_in_folder( dir_2_scan=r"D:\OneDrive\Documents\_TEST_\SAS_ADD", files_pattern="*.sas" ) print(wcl) # affiche Wcl(total_files=95, total_lines=20943) # # étalon *.log wcl = to.get_total_lines_in_folder( dir_2_scan=r"D:\OneDrive\Documents\_TEST_\SAS_ADD", files_pattern="*.log" ) print(wcl) # affiche Wcl(total_files=3, total_lines=587) # # scan multiple wcl = to.get_total_lines_in_folder( dir_2_scan=r"D:\OneDrive\Documents\_TEST_\SAS_ADD", files_pattern=("*.sas", "*.log") ) print(wcl) # affiche Wcl(total_files=98, total_lines=21530) qui est bien le total des 2 sous ensembles étalons =) # %% ######################################################################################################################## # Scan multiple avec exclusions # étalon 1 wcl = to.get_total_lines_in_folder( dir_2_scan=r"D:\OneDrive\Documents\_TEST_\SAS_ADD\_QUAL_", files_pattern=("*.sas", "*.log") ) print(wcl) # Wcl(total_files=93, total_lines=20869) # %% # étalon 2 wcl = to.get_total_lines_in_folder( dir_2_scan=r"D:\OneDrive\Documents\_TEST_\SAS_ADD\[ _BACKUP_POINT_0 ]", files_pattern=("*.sas", "*.log") ) print(wcl) # Wcl(total_files=4, total_lines=654) # %% # étalon 3 print( "Total lignes lues :", to.get_total_lines_in_file(r"D:\OneDrive\Documents\_TEST_\SAS_ADD\hello.sas") ) # Total lignes lues : 7 # %% # étalon 4 wcl = to.get_total_lines_in_folder( dir_2_scan=r"D:\OneDrive\Documents\_TEST_\SAS_ADD", files_pattern=("*.sas", "*.log") ) print(wcl) # Wcl(total_files=98, total_lines=21530) # 98 = 93 + 4 + 1 # 21530 = 20869 + 654 + 7 # %% # exclusions étalon wcl = to.get_total_lines_in_folder( dir_2_scan=r"D:\OneDrive\Documents\_TEST_\SAS_ADD", files_pattern=("*.sas", "*.log"), to_exclude=r"*_BACKUP_POINT_0*" ) print(wcl) # Wcl(total_files=94, total_lines=20876) # 94 = 98 - 4 # 20876 = 21530 - 654 # %% # exclusions finales wcl = to.get_total_lines_in_folder( dir_2_scan=r"D:\OneDrive\Documents\_TEST_\SAS_ADD", files_pattern=("*.sas", "*.log"), to_exclude=(r"*_BACKUP_POINT_0*", r"*SAS_ADD\hello.sas") ) print(wcl) # Wcl(total_files=93, total_lines=20869) # 93 = 98 - 4 - 1 # 20869 = 21530 - 654 - 7 # le compte y est! =}
-
corelibs.tools.
scan_dir
(dir_path, duplicated_files_indicator=False, skip_directories_properties=True, skip_pre_scan=False, ref_scan_file=None, caching=True, render='Excel', encoding='utf-8', std_print=False, gui_instance=None, force_excel_2_refresh=False)¶ Description
Permet de scanner un disque ou répertoire afin d’analyser son contenu, et en particulier d’y détecter des fichiers en doublon. Le scan s’appuie sur un caching pour réduire les temps de calcul et fonctionnera donc en mode delta à partir du 2ème scan.- Parameters
dir_path – indique chemin à analyser
duplicated_files_indicator –
indique s’il faut identifier les fichiers en doublon
valeurs possibles: False/Truevaleur par défaut: Falseskip_directories_properties –
indique s’il faut éviter le calcul des propriétés dossiers (pouvant être coûteux en temps d’exécution)
valeurs possibles: False/Truevaleur par défaut: Trueskip_pre_scan –
indique s’il faut éviter le préscan. Lorsqu’il est à True, alors le ref_scan_file sera pris en compte. Si ce dernier est à None, le cache sera utilisé (si existe), sinon une alerte sera levée. Et il faudrait donc préciser l’emplacement d’un fichier contenant les données scannées.
valeurs possibles: False/Truevaleur par défaut: Falseref_scan_file –
indique le fichier référentiel du préscan. Si la valeur est à None alors le cache du préscan sera pris en compte si existe. Sinon le fichier préscan fournit en entrée doit avoir les conditions suivantes :
être un fichier CSV, séparé par ;
avoir l’entête suivante “Technical ID”;”File Type”;”File Name”;”Owner”;”Last Access”;”Last Modification”;”OS Time”;”File Size”;”Bytes”;”KiloBytes”;”MegaBytes”;”GigaBytes”;”Fingerprint”;”Is Duplicated”
assurer l’unicité du champ “Technical ID”
caching –
indique s’il faut utiliser ou non le caching
valeurs possibles: False/Truevaleur par défaut: Truerender –
indique le rendu final
valeurs possibles: Excel, Web ou Appvaleur par défaut: Excelencoding – indique l’encodage de lecture/écriture
std_print –
indique s’il faut utiliser la sortie standard pour le printing
valeurs possibles: False/Truevaleur par défaut: Falsegui_instance – indique l’instance gui (pour l’interface visuelle, non utile en instructions codes)
force_excel_2_refresh –
indique s’il faut forcer le rafraichissement des fichiers caches Excel
valeurs possibles: False/Truevaleur par défaut: False
- Returns
- rien…
Warning
Le rendu “Web” n’est possible que sous Jupyter ou iPYthonNote
A partir du 2ème scan, si le calcul des doublons est souhaité, les fichiers du préscan ne se trouvant pas dans le cache seront calculés. Si les fichiers du préscan se trouvent dans le cache, alors le calcul se rafraichit dans les cas suivants :la taille du fichier a été modifiée
la date de modification a été changée
Exemple :
# scan_dir.py # %% from corelibs import tools # scan initial tools.scan_dir(r"D:\OneDrive\Documents\_TEST_\__LOGS__ - Copie", duplicated_files_indicator=True) # affichage sans recalcul (si cache existe) tools.scan_dir(r"D:\OneDrive\Documents\_TEST_\__LOGS__ - Copie", skip_pre_scan=True, render="Excel") # scan delta # à partir de maintenant, le dossier "D:\OneDrive\Documents\_TEST_\__LOGS__ - Copie" existe en cache et seuls les deltas # détectés seront calculés... tools.scan_dir(r"D:\OneDrive\Documents\_TEST_\__LOGS__ - Copie", duplicated_files_indicator=True)
Scan via code¶
Scan via interface¶
-
class
corelibs.tools.
Archive
¶ -
unzip
(yaml_file=None, archive_name=None, files_2_unzip=None, ignore_errors=False)¶ Description
Permet de décompresser les données- Parameters
yaml_file – fichier de configuration pour décompresser ; si utilisé en argument, les 2 arguments archive_name et files_2_unzip ne seront pas pris en compte. (ce fichier peut être créé manuellement ou être celui généré par la méthode
corelibs.tools.Archive.zip()
)archive_name – nom du fichier archive (avec son ou ses extensions) contenant les fichiers à décompresser avec son chemin absolu (i.e. “D:\OneDrive\Documents\_TEST_\NOM_ARCHIVE.7z”)
files_2_unzip –
le ou les fichiers à décompresser
si fichier simple, alors définir avec une chaîne de caractèressi liste de fichiers alors définir les différentes chaînes de caractères dans un tuple, séparé par des virgules (i.e. (“fichier 1”, “fichier 2”, …, “fichier n”))les noms des fichiers peuvent être précédés par un chemin ou non :sans le chemin en préfixe, alors l’emplacement du fichier à décompresser est celui du fichier archive
sinon le chemin en préfixe sera pris en priorité sur le chemin de l’archive pour la décompression
ignore_errors –
forcer l’exécution lorsqu’une erreur est levée
valeurs possibles: False/Truevaleur par défaut: False (cf. DEFAULT_IGNORE_ERROR dans Installation & Mise à jour)
- Returns
- code retour :
0 si OK
<> 0 si KO
Exemple :
# unarchive.py from corelibs import tools as to archive = to.Archive() # Décompression via un fichier de configuration YAML exit_code = archive.unzip(yaml_file=r"D:\OneDrive\Documents\_TEST_\TEST.yaml") # Décompression manuelle exit_code = archive.unzip( archive_name=r"D:\OneDrive\Documents\_TEST_\\/TEST.28112013.7z", # pas beau, mais on peut rentrer ce que l'on veut files_2_unzip=( # fichiers décompressés à la racine de l'archive (i.e. "D:\OneDrive\Documents\_TEST_\\/") r"D:\OneDrive\Desktop\1-01 Act One Questo Mar Rosso.m4a", "_éèçàoöôîïêëùûü;.txt", # fichier décompressé à un emplacement spécifique, ici "D:\OneDrive\Documents\_TEST_\A zip" r"D:\OneDrive\Documents\_TEST_\dossier compressé" ) )
-
zip
(yaml_file=None, archive_name=None, files_2_zip=None, delete_sources_files=False, ignore_errors=False)¶ Description
Permet de compresser les données- Parameters
yaml_file –
fichier de configuration pour compresser ; si utilisé en argument, les 2 arguments archive_name et files_2_zip ne seront pas pris en compte.
Un fichier de configuration ayant pour nom “archive_name.YAML” sera généré à la racine de archive_name et peut être utilisé en argument pour :compresser en mode mise à jour
décompresser (cf.
corelibs.tools.Archive.unzip()
)
archive_name – nom souhaité pour l’archive avec son chemin absolu pour le stockage (i.e. “D:\OneDrive\Documents\_TEST_\NOM_ARCHIVE”)
files_2_zip –
le ou les fichiers à compresser
si fichier simple, alors définir avec une chaîne de caractèressi liste de fichiers alors définir les différentes chaînes de caractères dans un tuple, séparé par des virgules (i.e. (“fichier 1”, “fichier 2”, …, “fichier n”))les noms des fichiers peuvent être précédés par un chemin ou non :sans le chemin en préfixe, alors l’emplacement du fichier à ziper est celui du fichier archive
sinon le chemin en préfixe sera pris en priorité sur le chemin de l’archive
delete_sources_files –
supprimer les fichiers sources une fois la compression finie (i.e. terminée sans erreur ou sans avoir été arrêtée par un autre processus)
valeurs possibles: False/Truevaleur par défaut: Falseignore_errors –
forcer l’exécution lorsqu’une erreur est levée
valeurs possibles: False/Truevaleur par défaut: False (cf. DEFAULT_IGNORE_ERROR dans Installation & Mise à jour)
- Returns
- code retour :
0 si OK
<> 0 si KO
Note
fichier s’entend au sens Unix du terme, i.e. fichier régulier ou répertoire
Exemple :
# archive.py from corelibs import lazy as lz, tools as to archive = to.Archive() # Compression via un fichier de configuration YAML exit_code = archive.zip(yaml_file=r"D:/OneDrive//\\//Documents\_TEST_\TEST.yaml") # pas beau, mais on peut rentrer ce que l'on veut... # Compression manuelle exit_code = archive.zip( archive_name=r"D:/OneDrive/Documents\_TEST_\MON_ARCHIVE_" + lz.get_timestamp(), files_2_zip=( # fichiers présents à la racine de l'archive (i.e. "D:/OneDrive/Documents\_TEST_") "1-01 Act One Questo Mar Rosso.m4a", "_éèçàoöôîïêëùûü;.txt", # fichier à un emplacement spécifique, ici "D:\OneDrive\Documents\_TEST_\A zip" r"D:\OneDrive\Documents\_TEST_\A zip\A zip - Copie" ) ) # stress test sur un fichier des établissements d'open data gouv.fr # taille fichier : 29 928 195 lignes, pour un poids total de 4.88 Go archive.zip( archive_name=r"D:\OneDrive\Desktop\StockEtablissement_utf8\StockEtablissement_utf8" + lz.get_timestamp(), files_2_zip=r"D:\OneDrive\Desktop\StockEtablissement_utf8\StockEtablissement_utf8.csv" )
Exemple Fichier YAML généré :
########################################################################################################################### # Généré le mercredi 16 décembre 2020 à 23:19:58 ########################################################################## ########################################################################################################################### archive: name: TEST.7z root: D:\OneDrive\Documents\_TEST_ files: - 1-01 Act One Questo Mar Rosso.m4a - _éèçàoöôîïêëùûü;.txt - D:\OneDrive\Documents\_TEST_\A zip\A zip - Copie ###########################################################################################################################
-
Dépendances¶
Description générale
Les dépendances sont installées automatiquement lors de l’installation/MAJ du package corelibs.
Dans le cas d’une création manuelle d’un nouvel environnement virtuel, selon le contexte de création, il est peut-être nécessaire de réinstaller manuellement les dépendances ci-dessous dans le-dit nouvel environnement.
Note
Pour mémoire, l’installation d’un package se fait avec cette commande
$ pip install nom_package
Et la mise à jour d’un package se fait avec cette commande
$ pip install nom_package -U
coloredlogs >=14.0
colorama >=0.4.3
schema >=0.7.2
ipython >=7.19.0
blessed >=1.17.11 (>1.17.6 non compatible avec inquirer==2.7.0)
enlighten >=1.6.2
click >=7.1.2
numpy ==1.19.3 (>=1.19.4 => numba crash!)
numba ==0.51.2 (>0.51.2 non compatible avec numpy>1.19.3)
PyYAML >=5.3.1
yamale >=3.0.4
stackprinter >=0.2.5
PySimpleGUI >=4.33.0
PyScaffold >=3.3
pandas >=1.2.0
dtale >=1.30.0
Liens utiles¶
Description générale
Tous les liens utiles sont listés ici, à jeter un oeil (voire même les 2 =þ)