#!/usr/bin/python3
# -*- coding: utf-8 -*-
########################################################################
#
# This file is part of python module <pySPC>.
# Copyright (C) 2013-2020 R. Marty
# (renaud.marty@developpement-durable.gouv.fr)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program (see COPYING.txt).
# If not, see <http://www.gnu.org/licenses/>.
#
########################################################################
"""
Objets natifs et convention de pyspc - Erreurs, avert. et vérificateurs
"""
from datetime import datetime as dt, timedelta as td
import inspect
import pandas as pnd
[docs]
class Error(Exception):
"""
Erreurs
"""
def __init__(self, value):
Exception.__init__(self)
self.parameter = value
def __str__(self):
return repr(self.parameter)
[docs]
def Warning(filename=None, msg=""):
"""
Avertissements
"""
if filename is None:
print(f"Avertissement : {msg}")
else:
print(f"Avertissement dans {filename}: {msg}")
[docs]
def DeprecationWarning(filename, msg):
"""
Avertissements obsolescence
"""
print(f"Obsolescence dans {filename}: {msg}. Cette fonctionnalité sera "
"retirée dans une prochaine version")
[docs]
def raise_valueerror(test, text='', warning=True):
"""
Lever une exception ValueError si le test est vrai
- Entrées
- test = (bool) Test
- text = (str) Texte à afficher en cas d'erreur
- warning = (bool) Exception levée si True
"""
if test and warning:
raise ValueError(text)
return test
[docs]
def set_default(arg=None, default=None, text=None, warning=False):
"""
Définir la valeur par défaut si un argument n'est pas défini
Parameters
----------
arg
Argument
default
Valeur par défaut
text : str
Message à imprimer si la valeur par défaut est retenue
Returns
-------
arg
Argument
"""
if arg is not None or default is None:
return arg
if text and not warning:
Information(True, text)
elif text:
Warning(None, text)
return default
def _caller_name(skip=2):
"""Get a name of a caller in the format module.class.method
`skip` specifies how many levels of stack to skip while getting caller
name. skip=1 means "who calls me", skip=2 "who calls my caller" etc.
An empty string is returned if skipped levels exceed stack height
https://stackoverflow.com/a/9812105
"""
stack = inspect.stack()
start = 0 + skip
if len(stack) < start + 1:
return ''
parentframe = stack[start][0]
name = []
module = inspect.getmodule(parentframe)
# `modname` can be None when frame is executed directly in console
if module:
name.append(module.__name__)
# detect classname
if 'self' in parentframe.f_locals:
name.append(parentframe.f_locals['self'].__class__.__name__)
codename = parentframe.f_code.co_name
if codename != '<module>': # top level usually
name.append(codename) # function or a method
# Avoid circular refs and frame leaks
# https://docs.python.org/2.7/library/inspect.html#the-interpreter-stack
del parentframe, stack
return ".".join(name)
[docs]
def check_bool(x):
"""Contrôler que l'objet 'x' est un booléen"""
if not isinstance(x, bool):
s = inspect.stack()[1].code_context[0]
s = s[s.find("(")+1:s.rfind(")")]
c = _caller_name()
raise ValueError(f"'{s}' doit être un booléen dans {c}")
return True
[docs]
def check_dataframe(x):
"""Contrôler que l'objet 'x' est un dataframe"""
if not isinstance(x, pnd.DataFrame):
s = inspect.stack()[1].code_context[0]
s = s[s.find("(")+1:s.rfind(")")]
c = _caller_name()
raise ValueError(f"'{s}' doit être un dataframe dans {c}")
return True
[docs]
def check_dict(x):
"""Contrôler que l'objet 'x' est un dictionnaire"""
if not isinstance(x, dict):
s = inspect.stack()[1].code_context[0]
s = s[s.find("(")+1:s.rfind(")")]
c = _caller_name()
raise ValueError(f"'{s}' doit être un dictionnaire dans {c}")
return True
[docs]
def check_dt(x):
"""Contrôler que l'objet 'x' est un datetime"""
if not isinstance(x, dt):
s = inspect.stack()[1].code_context[0]
s = s[s.find("(")+1:s.rfind(")")]
c = _caller_name()
raise ValueError(f"'{s}' doit être un datetime dans {c}")
return True
[docs]
def check_td(x):
"""Contrôler que l'objet 'x' est un timedelta"""
if not isinstance(x, td):
s = inspect.stack()[1].code_context[0]
s = s[s.find("(")+1:s.rfind(")")]
c = _caller_name()
raise ValueError(f"'{s}' doit être un timedelta dans {c}")
return True
[docs]
def check_in(x, y):
"""Contrôler que l'objet 'x' est inclus dans 'l'"""
# check_listlike(l)
if x not in y:
s = inspect.stack()[1].code_context[0]
s = s[s.find("(")+1:s.rfind(")")]
c = _caller_name()
raise ValueError(f"'{s}' doit être parmi '{y}', dans {c}")
return True
[docs]
def check_int(x):
"""Contrôler que l'objet 'x' est un entier"""
if not isinstance(x, int):
s = inspect.stack()[1].code_context[0]
s = s[s.find("(")+1:s.rfind(")")]
c = _caller_name()
raise ValueError(f"'{s}' doit être un entier dans {c}")
return True
[docs]
def check_float(x):
"""Contrôler que l'objet 'x' est un réel"""
if not isinstance(x, float):
s = inspect.stack()[1].code_context[0]
s = s[s.find("(")+1:s.rfind(")")]
c = _caller_name()
raise ValueError(f"'{s}' doit être un réel dans {c}")
return True
[docs]
def check_listlike(x):
"""Contrôler que l'objet 'x' est une similaire à une liste"""
if not isinstance(x, (list, tuple, set)):
s = inspect.stack()[1].code_context[0]
s = s[s.find("(")+1:s.rfind(")")]
c = _caller_name()
raise ValueError(f"'{s}' doit être similaire à une liste dans {c}")
return True
[docs]
def check_notnone(x):
"""Contrôler que l'objet 'x' n'est pas None"""
if x is None:
s = inspect.stack()[1].code_context[0]
s = s[s.find("(")+1:s.rfind(")")]
c = _caller_name()
raise ValueError(f"'{s}' doit être différent de None dans {c}")
return True
[docs]
def check_numeric(x):
"""Contrôler que l'objet 'x' est un entier ou un réel"""
if not isinstance(x, (int, float)):
s = inspect.stack()[1].code_context[0]
s = s[s.find("(")+1:s.rfind(")")]
c = _caller_name()
raise ValueError(f"'{s}' doit être un entier ou un réel dans {c}")
return True
[docs]
def check_str(x):
"""Contrôler que l'objet 'x' est une chaine de caractère"""
if not isinstance(x, str):
s = inspect.stack()[1].code_context[0]
s = s[s.find("(")+1:s.rfind(")")]
c = _caller_name()
raise ValueError(f"'{s}' doit être une chaine de caractères dans {c}")
return True