diff --git a/classes/utils/settings.py b/classes/utils/settings.py index f075402..0a24f52 100644 --- a/classes/utils/settings.py +++ b/classes/utils/settings.py @@ -1,6 +1,14 @@ -from warnings import warn +from sys import stdout, argv, executable +from gettext import gettext as _ +from logging import getLogger, StreamHandler, FileHandler, Formatter from pathlib import Path +_formatter = Formatter( + fmt = '${levelname}:${name}:${message}', + style = '$' , +) +_program_cmd = executable + ' ' + argv[0] + class Settings: """ Settings manager @@ -17,12 +25,16 @@ class Settings: self.set_no_cache() self.set_output() self.set_verbose() + self.set_log_file() self.set_wave_cal() # configuration change if len( arguments ) < 1: raise Exception( - 'type \'' + __file__ + ' -h\' for more information' + _( ( + 'no argument given, type \'{program} -g\' for more' + ' information' + ) ).format( program = _program_cmd ) ) index = 0 @@ -31,22 +43,25 @@ class Settings: if argument[0] == '-': if len( argument ) < 2: raise Exception( - 'unknown argument, type \' + __file__ + \' -h' + - ' for more information' + _( ( + 'unknown argument {argument}, type ' + '\'{program} -h\' for more information' + ) ).format( + program = _program_cmd, + argument = argument , + ) ) if argument[1] != '-': if argument == '-h': argument = '--help' elif argument == '-V': argument = '--version' - elif argument == '-v': - argument = '--verbose' elif argument == '-n': argument = '--no-cache' elif argument == '-c': if index == len( arguments ) - 1: raise Exception( - 'cache have to take a value' + _( 'cache have to take a value' ) ) arguments[ index + 1 ] = '--cache=' + \ arguments[ index + 1 ] @@ -55,7 +70,7 @@ class Settings: elif argument == '-o': if index == len( arguments ) - 1: raise Exception( - 'output have to take a value' + _( 'output have to take a value' ) ) arguments[ index + 1 ] = '--output=' + \ arguments[ index + 1 ] @@ -64,7 +79,10 @@ class Settings: elif argument == '-w': if index == len( arguments ) - 1: raise Exception( - 'wavelength calibration have to take a value' + _( ( + 'wavelength calibration have to take' + ' a value' + ) ) ) arguments[ index + 1 ] = '--wavelength=' + \ arguments[ index + 1 ] @@ -73,17 +91,44 @@ class Settings: elif argument == '-i': if index == len( arguments ) - 1: raise Exception( - 'intensity calibration have to take a value' + _( ( + 'intensity calibration have to take' + ' a value' + ) ) ) arguments[ index + 1 ] = '--intensity=' + \ arguments[ index + 1 ] index += 1 continue + elif argument == '-l': + if index == len( arguments ) - 1: + raise Exception( + _( ( + 'log file have to take a value' + ) ) + ) + arguments[ index + 1 ] = '--log-file=' + \ + arguments[ index + 1 ] + index += 1 + continue + elif argument == '-v': + if index == len( arguments ) - 1: + raise Exception( + _( 'verbosity level have to take a value' ) + ) + arguments[ index + 1 ] = '--verbose=' + \ + arguments[ index + 1 ] + index += 1 + continue else: raise Exception( - 'unknown argument "' + argument + \ - '", type \'' + __file__ + \ - ' -h\' for more information' + _( ( + 'unknown argument {argument}, type' + '\'{program} -h\' for more information' + ) ).format( + program = _program_cmd, + argument = argument , + ) ) if argument[1] == '-': # not elif because argument # can change in the last if @@ -93,10 +138,13 @@ class Settings: elif argument == '--version': print( self.version() ) exit() - elif argument == '--verbose': - self.set_verbose( True ) elif argument == '--no-cache': self.set_no_cache( True ) + elif ( + len( argument ) > 10 and + argument[ : 10 ] == '--verbose=' + ): + self.set_verbose( argument[ 10 : ] ) elif ( len( argument ) > 8 and argument[ : 8 ] == '--cache=' @@ -117,18 +165,34 @@ class Settings: argument[ : 12 ] == '--intensity=' ): self.set_inte_cal( argument[ 12 : ] ) + elif ( + len( argument ) > 11 and + argument[ : 11 ] == '--log-file=' + ): + self.set_log_file( argument[ 11 : ] ) else: raise Exception( - 'unknown argument "' + argument + \ - '", type \'' + __file__ + ' -h\' ' + \ - 'for more information' + _( ( + 'unknown argument {argument}, type' + '\'{program} -h\' for more information' + ) ) ) else: self.set_input( argument ) index += 1 + logger = getLogger( 'naroo reader' ) + if not logger.hasHandlers(): + handler = StreamHandler( stdout ) + handler.setFormatter( + _formatter, + ) + logger.addHandler( + handler, + ) + if self.input == None: - raise Exception( 'input should be given' ) + raise Exception( _( 'input should be given' ) ) def set_cache( self , cache = None ): """ @@ -142,7 +206,7 @@ class Settings: self.cache = cache else: raise TypeError( - 'cache should be a path' + _( 'cache should be a path' ) ) def set_input( self , input = None ): """ @@ -156,11 +220,13 @@ class Settings: self.input = input else: raise TypeError( - 'input should be a path' + _( 'input should be a path' ) ) if self.input != None and not self.input.is_file(): raise IOError( - 'could not open ' + str( self.input ) + _( 'could not open {input}' ).format( + input = self.input, + ) ) def set_inte_cal( self , intensity_calibration = None ): @@ -175,11 +241,41 @@ class Settings: self.inte_cal = intensity_calibration else: raise TypeError( - 'intensity calibration should be a path' + _( 'intensity calibration should be a path' ) ) if self.inte_cal != None and not self.inte_cal.is_file(): raise IOError( - 'could not open ' + str( self.inte_cal ) + _( 'could not open {intensity_file}' ).format( + intensity_file = self.inte_cal, + ) + ) + + def set_log_file( self , log_file = None ): + """ + Setter for log file (None or path) + """ + if isinstance( log_file , str ): + self.log_file = Path( log_file ) + elif isinstance( log_file , Path ): + self.log_file = log_file + elif log_file == None: + self.log_file = log_file + else: + raise TypeError( + _( 'log file should be a path' ) + ) + + if self.log_file != None: + logger = getLogger( 'naroo reader' ) + handler = FileHandler( + filename = str( log_file ), + mode = 'a' , + ) + handler.setFormatter( + _formatter, + ) + logger.addHandler( + handler, ) def set_no_cache( self , no_cache = False ): @@ -190,7 +286,7 @@ class Settings: self.no_cache = no_cache else: raise TypeError( - 'no_cache option should be a boolean' + _( 'no_cache option should be a boolean' ) ) def set_output( self , output = 'data.fits' ): @@ -203,25 +299,42 @@ class Settings: self.output = output else: raise TypeError( - 'output should be a path' + _( 'output should be a path' ) ) if self.output.is_file(): - warn( - str( self.output ) + ' already exists, it will be ' + - 'overwritten', - UserWarning , + logger = getLogger( 'naroo reader' ) + logger.warning( + _( + '{output} already exists, it will be overwritten' + ).format( output = self.output ) ) - def set_verbose( self , verbose = False ): + def set_verbose( self , verbose = 'WARNING' ): """ - Setter for verbosity flag (bool) + Setter for verbose level (string) """ - if isinstance( verbose , bool ): - self.verbose = verbose + if isinstance( verbose , str ): + self.verbose = verbose.upper() + if verbose not in [ + 'CRITICAL', + 'ERROR' , + 'WARNING' , + 'INFO' , + 'DEBUG' , + 'NOTSET' , + ]: + raise ValueError( + _( ( + 'verbose level must be one of the listed ones' + 'in python documentation' + ) ) + ) else: raise TypeError( - 'verbose should be a boolean' + _( 'verbose level should be a string' ) ) + logger = getLogger( 'naroo reader' ) + logger.setLevel( self.verbose ) def set_wave_cal( self , wavelength_calibration = None ): """ @@ -235,40 +348,40 @@ class Settings: self.wave_cal = wavelength_calibration else: raise TypeError( - 'wavelength calibration should be a path' + _( 'wavelength calibration should be a path' ) ) if self.wave_cal != None and not self.wave_cal.is_file(): raise IOError( - 'could not open ' + str( self.wave_cal ) + _( 'could not open {wavelength_file}' ).format( + wavelength_file = self.wave_cal + ) ) def help( self ): - return '\ -naroo_reader [options...] input\ -\n -w wavelength wavelength calibration file, default to None.\ -\n None means no wavelength interpolation\ -\n -i intensity intensity calibration file, default to None.\ -\n None means no intensity interpolation\ + return 'naroo_reader [options...] input\ \n -c --cache use given cache file to store new temporary\ \n data or use old ones.\ -\n -h --help show this help and quit\ +\n -h --help show this help and quit.\ +\n -i --intensity intensity calibration file, default to None.\ +\n None means no intensity interpolation\ +\n -l --log-file file where to log event.\ \n -n --no-cache do not use already existing cache file.\ \n If cache is defined, the cache file will be\ \n overwrited.\ -\n If cache is None, it does nothing\ -\n -o --output Output file. Default to data.fits\ -\n -V --version show version number and quit\ -\n -v --verbose show more information to help debugging\ - ' +\n If cache is None, it does nothing.\ +\n -o --output Output file. Default to data.fits.\ +\n -V --version show version number and quit.\ +\n -v --verbose set logging level help debugging.\ +\n -w wavelength wavelength calibration file, default to None.\ +\n None means no wavelength interpolation.' def __str__( self ): - return '\ -current settings:\ + return 'current settings:\ \n cache: ' + str( self.cache ) + '\ \n input: ' + str( self.input ) + '\ \n intensity calibration: ' + str( self.inte_cal ) + '\ \n no cache flag: ' + str( self.no_cache ) + '\ \n output: ' + str( self.output ) + '\ -\n verbose flag: ' + str( self.verbose ) + '\ -\n wavelength calibration: ' + str( self.wave_cal ) + '\ - ' +\n logging level: ' + str( self.verbose ) + '\ +\n log-file: ' + str( self.log_file ) + '\ +\n wavelength calibration: ' + str( self.wave_cal )