Skip to content
mar 28 / David Regnier

Utilitaires Python, méthodes statiques

Voici un fichier « helper » Python mis à disposition pour vos développements (classes et méthodes statiques):

Prérequis:

#    Mode: Python; tab-width: 4
#    Id: helper_misc.py
#    Author: David REGNIER
#    Description: 

# ======================================================================
# Copyright 2014 by David REGNIER
#
#                         All Rights Reserved
#
# Permission to use, copy, modify, and distribute this software and
# its documentation for any purpose and without fee is hereby
# granted, provided that the above copyright notice appear in all
# copies and that both that copyright notice and this permission
# notice appear in supporting documentation, and that the name of David
# REGNIER be used in advertising or publicity pertaining to
# distribution of the software without specific, written prior
# permission.
# ======================================================================

# Import common lib
import xml.parsers.expat
import py_compile, traceback
import os, re, sys, time
from datetime import datetime

# Lib for XML
try:
    from lib.xml.etree import ElementTree
except ImportError:
    ElementTree = None
    sys.stderr.write('ERROR: %s\n' % traceback.format_exc())
    sys.exit();

"""Begin LogStats class"""
class LogStats(object):
    # Description: Constructor
    #              Init stats log file
    #              Call sample: sys.stdout = LogStats()
    # @return: void
    def __init__(self, sOutputFile = os.getcwd() + "\\log\\" + 'stats.log'):
        self.oConsole = sys.stdout
        self.sFile = open(sOutputFile, 'w')

    # Description: Write flow to console and file
    #
    # @param self: Constructor parameters
    # @param sFlow: String to write
    # @return: int
    def write(self, sFlow):
        try:
            if sFlow <> '':
                self.oConsole.write(sFlow) # Write to console
                self.sFile.write(sFlow) # Write to stats log file
            return 0
        except Exception:
            sys.stderr.write('ERROR: %s\n' % traceback.format_exc())
            return 1
"""End LogStats class"""

"""Begin ToolsBox class"""
class ToolsBox(object):
    # Description: Create folder tree for module
    #              Call sample: ToolsBox.init_folder_tree(sFolder1, sFolder2, ...)
    # @param *args: Folder1, Folder2, ...
    # @return: int
    @staticmethod
    def init_folder_tree(*args):
        try:
            for element in args:
                if not os.path.exists(element):
                    os.mkdir(element)
            return 0
        except Exception:
            sys.stderr.write('ERROR: %s\n' % traceback.format_exc())
            return 1 

    # Description: Compile Python script
    #              Call sample: ToolsBox.init_compile(sInputPyScript = __file__)
    # @param sInputPyScript: Python Script file name
    # @return: int
    @staticmethod
    def init_compile(sInputPyScript = ''):
        try:
            if os.path.exists(sInputPyScript):
                py_compile.compile(sInputPyScript)
            return 0
        except Exception:
            sys.stderr.write('ERROR: %s\n' % traceback.format_exc())
            return 1    

    # Description: Init error log file
    #              Call sample: ToolsBox.init_error_log()
    # @return: int
    @staticmethod
    def init_error_log():
        try:
            if not os.path.exists('log'):
                os.makedirs('log')
            fileSocketError = open(os.getcwd() + "\\log\\" + 'error.log', 'w')
            sys.stderr = fileSocketError
            return 0
        except Exception:
            sys.stderr.write('ERROR: %s\n' % traceback.format_exc())
            return 1

    # Description: Return current date, convert date string to datetime object
    #              Call sample: ToolsBox.get_current_date('02', '2012')
    # @param sMonthName: Month MM format
    # @param sYearName: Year YYYY format
    # @return: mixed (datetime/int)
    @staticmethod
    def get_current_datetime_by_string(sMonthName, sYearName):
        try:
            sDate = sYearName + '-' + sMonthName + '-' + time.strftime('%d')
            return datetime.strptime(sDate, '%Y-%m-%d')
        except Exception:
            sys.stderr.write('ERROR: %s\n' % traceback.format_exc())
            return 1  

    # Description: Get first day of month
    #              Call sample: ToolsBox.get_first_day_of_month(date.today(), '-'))
    # @param oTodayDate: Current datetime object
    # @param sFormat: Current format, default /
    # @return: mixed (string/int)
    @staticmethod
    def get_first_day_of_month(oTodayDate, sFormat = '/'):
        try:
            return date(oTodayDate.year, oTodayDate.month, 1).strftime('%Y' + sFormat + '%m' + sFormat + '%d')
        except Exception:
            sys.stderr.write('ERROR: %s\n' % traceback.format_exc())
            return 1			

    # Description: Get end day of month
    #              Call sample: ToolsBox.get_end_day_of_month(date.today(), '-'))
    # @param oTodayDate: Current datetime object
    # @param sFormat: Current format, default /
    # @return: mixed (string/int)
    @staticmethod
    def get_end_day_of_month(oTodayDate, sFormat = '/'):
        try:
            iDaysNumberInMonth = calendar.monthrange(oTodayDate.year, oTodayDate.month)[1]
            return date(oTodayDate.year, oTodayDate.month, iDaysNumberInMonth).strftime('%Y' + sFormat + '%m' + sFormat + '%d')
        except Exception:
            sys.stderr.write('ERROR: %s\n' % traceback.format_exc())
            return 1 

    # Description: Check for null element in input array
    #              Call sample: ToolsBox.check_empty_element_in_array(aInputArray, 6)
    # @param aInputArray: Input array
    # @param iNbElement: Number of element in array
    # @return: int
    @staticmethod
    def check_empty_element_in_array(aInputArray, iNbElement):
        try:
            if len(filter(bool, aInputArray)) == iNbElement:
                return 0
            else:
                sys.stderr.write('ERROR: %s\n' % 'One key element cannot be empty (you should have ' + str(iNbElement) + ' element(s)), in this array : ' + str(aInputArray))
                sys.exit()
        except Exception:
            sys.stderr.write('ERROR: %s\n' % traceback.format_exc())
            return 1  

    # Description: Check if file exist regarding his pattern name
    #              Call sample: ToolsBox.check_input_file(sInputFolder, sInputFile)
    # @param sInputFolder: Input folder
    # @param sInputFile: Input file
    # @return: mixed (string/int)
    @staticmethod
    def check_input_file(sInputFolder = '', sInputFile = ''):
        try:
            if sInputFolder <> '' and sInputFile <> '':
                i = 0
                for sFileName in os.listdir(sInputFolder):
                    if sInputFile[:5] in sFileName:
                        i += 1
                        sRealFileName = sFileName
                if i <> 1:
                    sys.stderr.write('ERROR: %s\n' % 'The input file seems to have a wrong name, or does not exist, or multiple existence')
                    sys.exit()
                else:
                    return sRealFileName
            else:
                sys.exit()
        except Exception:
            sys.stderr.write('ERROR: %s\n' % traceback.format_exc())
            return 1 

    # Description: XML validation
    #              Call sample: ToolsBox.check_xml_format(sOutputFile)
    # @param sOutputFile: XML output file
    # @return: boolean
    @staticmethod
    def check_xml_format(sOutputFile = ''):
        try:
            if sOutputFile <> '':
                parser = xml.parsers.expat.ParserCreate()
                parser.ParseFile(open(sOutputFile, "r"))
            return True
        except Exception:
            sys.stderr.write('ERROR: %s\n' % traceback.format_exc())
            return False

    # Description: Return current datetime
    #              Call sample: ToolsBox.get_current_datetime('%Y-%m-%dT%H:%M:%S')
    # @param sFormat: Format type
    # @return: mixed (string/int)
    @staticmethod
    def get_current_datetime(sFormat = ''):
        try:
            return time.strftime(sFormat)
        except Exception:
            sys.stderr.write('ERROR: %s\n' % traceback.format_exc())
            return 1

    # Description: Return files by folder
    #              Call sample: ToolsBox.get_files_by_folder('/dev/data/', 'full')
    # @param sFolder: Folder
    # @param sFullPath: (optional) If we need full path
    # @return: mixed (array/int)
    @staticmethod
    def get_files_by_folder(sFolder = '', sFullPath = ''):
        try:
            if sFolder:
                aFileName = []
                aFileNameFullPath = []
                for sPath, sFolder, sFiles in os.walk(sFolder):
                    for sFileName in sFiles:
                        if ToolsBox.check_empty_file(os.path.join(sPath, sFileName)):
                            aFileNameFullPath.append(os.path.join(sPath, sFileName))
                            aFileName.append(sFileName)
                if sFullPath:
                    return aFileNameFullPath
                else:
                    return aFileName
            else:
                sys.stderr.write('ERROR: %s\n' % 'The input folder is empty')
                return 1
        except Exception:
            sys.stderr.write('ERROR: %s\n' % traceback.format_exc())
            return 1

    # Description: Return matched files list by search pattern
    #              Call sample: ToolsBox.get_files_by_matched_pattern(aFilesList, 'FRA000000123', 'full')
    # @param aFilesList: Array files
    # @param sSearchedPattern: String to search
    # @param sPath: If we need full path, 'full'
    # @return: mixed (array/int)
    @staticmethod
    def get_files_by_matched_pattern(aFilesList, sSearchedPattern = '', sPath = ''):
        try:
            if aFilesList:
                aMatchedFilesList = []
                for sFileName in aFilesList:
                    for line in enumerate(open(sFileName)):
                        sFile = sFileName
                        if sPath:
                            sFile = os.path.basename(sFileName)
                        if sSearchedPattern:
                            if re.search(sSearchedPattern, str(line), re.IGNORECASE):
                                aMatchedFilesList.append(sFile)
                                break
                return aMatchedFilesList
            else:
                sys.stderr.write('ERROR: %s\n' % 'The files list is empty')
                return 1
        except Exception:
            sys.stderr.write('ERROR: %s\n' % traceback.format_exc())
            return 1

    # Description: Create XML node
    #              Call sample: ToolsBox.set_xml_node(document, "node_name", parent_node, ["node_content"], ["attribute_key"], ["attribute_content"])
    # @param oDoc: Current xml.dom.minidom.Document
    # @param sNodeName: XML node name
    # @param oParentNode: XML parent node
    # @param sNodeContent: (Optional) XML node content
    # @param sXMLAttributeKey: (Optional) XML attribute key name
    # @param sXMLAttributeContent: (Optional) XML attribute content
    # @return: mixed (object/int)
    @staticmethod
    def set_xml_node(oDoc, sNodeName = '', oParentNode = '', sNodeContent = '', sXMLAttributeKey = '', sXMLAttributeContent = ''):
        try:
            oXMLNode = oDoc.createElement(sNodeName)
            if sXMLAttributeKey <> '':
                oXMLNode.setAttribute(sXMLAttributeKey, sXMLAttributeContent)
                oParentNode.appendChild(oXMLNode)
            if sNodeContent <> '':
                sXMLContent = oDoc.createTextNode(sNodeContent)
                oXMLNode.appendChild(sXMLContent)
            oParentNode.appendChild(oXMLNode)
            return oXMLNode
        except Exception:
            sys.stderr.write('ERROR: %s\n' % traceback.format_exc())
            return 1

    # Description: Check for empty file
    #              Call sample: ToolsBox.check_empty_file(sInputFile)
    # @param sInputFile: Input file to check
    # @return: boolean
    @staticmethod
    def check_empty_file(sInputFile = ''):
        try:
            if os.stat(sInputFile).st_size <> 0:
                return True
        except Exception:
            sys.stderr.write('ERROR: %s\n' % traceback.format_exc())
            return False

    # Description: Get first subelement by tree element by match tag
    #              Call sample: ToolsBox.get_xml_node_value(oTree, 'ERS/VES', 'DATI', sNodeType = 'attrib')
    # @param oTree: Input element tree object
    # @param sXMLPath: Path to tree
    # @param sMatch: What tag we should match
    # @param sNodeType: What node type we should match
    # @return: mixed(string/int)
    @staticmethod
    def get_xml_node_value(oTree, sXMLPath, sMatch, sNodeType = 'text'):
        try:
            if sNodeType == 'text':
                # For text value
                for node in oTree.find(sXMLPath):
                    if node.tag == sMatch:
                        return node.text
            else:
                # For attrib value
                for node in oTree.findall(sXMLPath):
                    if node.tag == sXMLPath.split('/')[-1]:
                        return node.attrib[sMatch]
        except Exception:
            sys.stderr.write('ERROR: %s\n' % traceback.format_exc())
            sys.exit()
            return 1

    # Description: Get first subelement by tree element
    #              Call sample: ToolsBox.get_first_subelement_tag_name(oTree, 'ERS/VES')
    # @param oTree: Input element tree object
    # @param sXMLPath: XML Path to search for
    # @return: mixed(string/int)
    @staticmethod
    def get_first_subelement_tag_name(oTree, sXMLPath):
        try:
            for node in oTree.find(sXMLPath):
                return node.tag
        except Exception:
            sys.stderr.write('ERROR: %s\n' % traceback.format_exc())
            sys.exit()
            return 1              

    # Description: Rename input file
    #                  Call sample: ToolsBox.set_filename(sInputFile, 'FRA000735220', sFromDate = '20110822', sToDate = '20150822'):
    # @param sInputFile: Input file name
    # @param sCFR: CFR name
    # @param sFromDate: From date
    # @param sToDate: To date
    # @return: mixed (string/int)
    @staticmethod
    def set_filename(sInputFile, sCFR, sFromDate = '', sToDate = ''):
        try:
            sPattern = sCFR.upper()
            if sFromDate:
                sPattern += '_FROM_' + sFromDate
            if sToDate:
                sPattern += '_TO_' + sToDate
            newFileName = sInputFile.replace('%pattern%', sPattern)
            if os.path.exists(newFileName):
                os.remove(newFileName) # Remove first
            os.rename(sInputFile, newFileName)
            return newFileName
        except Exception:
            sys.stderr.write('ERROR: %s\n' % traceback.format_exc())
            sys.exit()
            return 1

    # Description: Return current monday and current sunday from given year, week number
    #              Call sample: ToolsBox.get_start_end_weekday(year, week_number)
    # @param year: Current year
    # @param week_number: Current weeknumber
    # @return: datetime(monday, sunday)
    @staticmethod
    def get_start_end_weekday(year, week_number):
        try:
            if year and week_number:
                jan = datetime(year, 1, 1)
                if jan.isocalendar()[1] == 1:
                    week1 = jan # week1 contains jan
                else:
                    # Var jan is in the last year, so add 7 days to get the next week which should be week 1
                    week1 = jan + timedelta(7)

                # Now adjust week1 so we'll get the start of that week
                week1 = week1 - timedelta(week1.weekday())

                # Now we have the start date of week_number 1
                # Calculate the start date of the week we want
                weekday_start = week1 + timedelta(7 * (week_number - 1))

                # Just add 6 days to have sunday datetime
                weekday_end = weekday_start + timedelta(days=6)

                return weekday_start, weekday_end
        except Exception:
            sys.stderr.write('ERROR: %s\n' % traceback.format_exc())
            sys.exit()
"""End ToolsBox class"""   

"""Begin ToolsValidator class"""
class ToolsValidator(object):
    # Description: Constructor
    #              Init validator
    # @param self: Constructor parameter
    # @param cfr: CFR
    # @param sFromDate: From date
    # @param sToDate: To date
    # @return: void
    def __init__(self, cfr = '', sFromDate = '', sToDate = ''):
        self.cfr = cfr
        self.sFromDate = sFromDate
        self.sToDate = sToDate

    # Description: CFR validation
    #
    # @param self: Constructor parameter
    # @param string: Input string to valid
    # @return: int
    def valid_cfr(self, sCFR = ''):
        try:
            if not sCFR:
                raise Exception('%s' % 'CFR cannot be empty')
            elif len(sCFR) <> 12:
                raise Exception('%s' % 'Wrong CFR length : ' + sCFR)
            elif not sCFR.isalnum():
                raise Exception('%s' % 'Wrong CFR format, should be alphanumeric : ' + sCFR)
            return 0
        except Exception:
            sys.stderr.write('ERROR: %s\n' % traceback.format_exc())
            sys.exit()
            return 1

    # Description: DATE validation
    #
    # @param self: Constructor parameter
    # @param string: Input string date to valid
    # @return: int
    def valid_date(self, sInputDate = ''):
        try:
            if not sInputDate:
                raise Exception('%s' % 'DATE cannot be empty')
            elif len(sInputDate) <> 8:
                raise Exception('%s' % 'Wrong DATE length' + sInputDate)
            elif not sInputDate.isdigit():
                raise Exception('%s' % 'Wrong DATE type, should be only numeric : ' + sInputDate)
            try:
                datetime.strptime(sInputDate, '%Y%m%d')
            except ValueError:
                raise ValueError('%s' % 'Incorrect DATE format, should be YYYYMMDD, or wrong DATE : ' + sInputDate)
            return 0
        except Exception:
            sys.stderr.write('ERROR: %s\n' % traceback.format_exc())
            sys.exit()
            return 1
"""End ToolsValidator class"""
La classe LogStats est pratique si vous souhaitez rediriger les logs vers un fichier et la console en même temps, les méthodes statiques sont disponibles en vrac, il vous faudra les modifier en fonction de vos besoins.
Laisser un commentaire


+ 6 = 11