Code source de pyspc.io.dbase.mdb

#!/usr/bin/python3
# -*- coding: utf-8 -*-
########################################################################
#
# This file is part of python module <pyspc>.
# Copyright (C) 2013-2021  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/>.
#
########################################################################
"""
Bases de données ACCESS
"""
from datetime import datetime as dt, timedelta as td
import os.path
import pyspc.core.exception as _exception
import pyspc.io.dbase.dbase as _dbase


REF_DTIME = dt(1899, 12, 31, 0, 0)  #
"""Date initiale, date 'zéro' pour Access"""

# DRIVER = "{Microsoft Access Driver (*.mdb)}"  # version 32 bits
DRIVER = "Microsoft Access Driver (*.mdb, *.accdb)"  # version 64 bits
"""Driver de lecture de base Access."""


[docs] class Mdb(_dbase.Dbase): """ Bases Access (.mdb). Attributes ---------- filename : str Nom du fichier _dbase_connect : pyodbc Object de connexion pyodbc _dbase_cursor : pyodbc Curseur de pyodbc sql : str Requête SQL _tables : str Tables de la base """ def __init__(self, filename=None): """ Initialiser l'instance Mdb. Parameters ---------- filename : str Nom du fichier Access (.mdb) """ super().__init__(filename=filename)
[docs] def connect(self): """ Créer la connexion à la base de données et le curseur pyodbc. .. warning:: Cette méthode nécessite l'import de la bibliothèque tierce pyodbc """ import pyodbc # Contrôles if not os.path.exists(self.filename): raise OSError(f"Base de données inconnue {self.filename}") # Ouverture de la base self._dbase_connect = pyodbc.connect( driver=DRIVER, DBQ=self.filename) self._dbase_cursor = self._dbase_connect.cursor()
[docs] def execute(self, warning=True): """ Exécution de la requête SQL. Parameters ---------- warning : bool Afficher les avertissements. Par défaut: True Returns ------- list or None Eléments retenus par la requête SQL .. warning:: Cette méthode nécessite l'import de la bibliothèque tierce pyodbc """ import pyodbc data = None if self.sql is None: raise ValueError('Requête SQL non définie') if not isinstance(self.sql, str): raise ValueError('Requête SQL incorrecte') if not isinstance(self._dbase_cursor, pyodbc.Cursor): raise OSError('Curseur MDB incorrect ou non défini') try: self._dbase_cursor.execute(self.sql) # except ValueError: except pyodbc.Error as pe: _exception.Warning( __name__, "erreur d'exécution de la requête SQL\n" f"'{self.sql}'.\nLa lib 'pyodbc' indique ceci : {pe.args[-1]}") else: try: data = self._dbase_cursor.fetchall() except pyodbc.ProgrammingError: if 'INSERT' not in self.sql and 'UPDATE' not in self.sql: _exception.Warning( __name__, "une erreur est survenue lors de la " "récupération des éléments demandés par SQL. ") data = None except pyodbc.DataError: data = None if warning: _exception.Warning( __name__, "une erreur est survenue lors de la " "lecture de la base Access. " "Cela peut provenir de la " "lecture de la date") return data return data
[docs] @staticmethod def from_datetime(dtime=None, fmt=None, tolerance=0): """ Convertir un <string> ou un <datetime> au format accepté par Access. - Convertir les dates du format 'str' au format 'datetime.datetime' - Convertir en réel: mode de stockage des dates dans Access - Il faut ajouter 1 jour lors du calcul du flottant car 366j en 1900 (Access) et 365j en 1900 (datetime.datetime) - Il faut enlever/ajouter 60 sec. (tolerance) dans le calcul du flottant pour contrer le pb de précision numérique SQL/ACCESS Parameters ---------- dtime : datetime ou str Date à convertir fmt : str Format de la date, si définie comme un str tolerance : int Tolérance en secondes. Par défaut: 0 Returns ------- float Valeur réelle correspondant à la date et à la tolérance """ if isinstance(dtime, str): _exception.check_str(fmt) dtime = dt.strptime(dtime, fmt) _exception.check_dt(dtime) _exception.check_numeric(tolerance) dtime = dtime - REF_DTIME + td(days=1) access_dtime = dtime.days + float(dtime.seconds + tolerance) / 86400 return access_dtime