def check_file(file_, ignorable_=True, verbose_=True): ''' Check if file exists && is readable && not empty status: finished return: file_ / None raise: IOError ''' try: with open(file_, mode="r", encoding="utf-8") as f: # If file exists && is readable... from os.path import isfile if not isfile(file_): # ... && is a normal file (no block device, etc) ... raise OSError("File " + file_ + " is not a regular file") from os import stat if stat(f.fileno()).st_size <= 0: # ... && is not empty ... raise OSError("File " + file_ + " is empty") f.readline() # ... && is really an unicode file ... except (IOError, TypeError, OSError, UnicodeDecodeError) as exception_msg: if skj_std.arguments_values['ignoreerrors'] and ignorable_ == True: skj_std.print_msg_verbose(err_=skj_std.create_error_msg("PYTHON", exception_msg)) return None else: raise IOError(skj_std.create_error_msg("PYTHON", exception_msg, False)) else: return file_ # ... then it has passed all basic tests
def check_effects_syntax(): ''' Check for allowed syntax status: finished return: dict raise: ValueError ''' valid_effects = dict() f = skj_std.arguments_values['effectparams'] # wtf is this mess, right? u = [l.split(":") for l in f] # well, if I'll ever want to piss someone in team... c = [f for l in u for f in l] # ... i'll play on stubborn, selfish asshole ... k = [f.split("=") for f in c] # ... and write my code just like folks at MFF ... _ = {e[0]:e[1] for e in k if len(e) > 1} # ... write math! parsed_effects = _ # ouky douky, lets get back to work for effect in parsed_effects: if effect in skj_std.allowed_effects: if parsed_effects[effect] in skj_std.allowed_effects[effect]: valid_effects[effect] = parsed_effects[effect] continue if skj_std.arguments_values['ignoreerrors']: skj_std.print_msg_verbose(err_=skj_std.create_error_msg("INVALID_VALUE", effect)) else: raise ValueError(skj_std.create_error_msg("INVALID_VALUE", effect)) return valid_effects
def set_animation_properties(): ''' Set properties of animation like speed, time, num of frames, num of records, type, etc status: finished return: None raise: TypeError, IndexError, ValueError ''' # Get animation type skj_std.arguments_values['animation_type'] = determine_anim_type() # raise IndexError # Then calculate the number of valid lines (valid line is also called 'record') skj_std.arguments_values['records'] = 0 # File with zero records should never exist for lines_file in get_anim_records(): if skj_std.arguments_values['animation_type'] == "multiplot": # Multiplot animation has as many records as the longest file has lines if lines_file > skj_std.arguments_values['records']: skj_std.arguments_values['records'] = lines_file else: # Oneline animation has sum(all_lines) records skj_std.arguments_values['records'] += lines_file # Calculate correct speed && fps && frames && time calculate_sfft() # raise VauleError, ArithmeticError (catch AE? => if ignoreerrors: speed = 0 (see code below)) # Correct speed/fps if it is too low (< 1), cause that leads to crazy long create_speed_seq() && generate_anim() if skj_std.arguments_values['speed'] < 1 or skj_std.arguments_values['fps'] < 1: if skj_std.arguments_values['ignoreerrors']: skj_std.print_msg_verbose(err_=skj_std.create_error_msg("TOO_SMALL_ANIM", \ str(skj_std.arguments_values['speed']) + \ "/" + str(skj_std.arguments_values['fps']))) skj_std.arguments_values['speed'] = skj_std.arguments_defaults['speed'] skj_std.arguments_values['fps'] = skj_std.arguments_defaults['fps'] skj_std.arguments_values['time'] = skj_std.arguments_defaults['time'] calculate_sfft() else: raise ValueError(skj_std.create_error_msg("TOO_SMALL_ANIM", \ str(skj_std.arguments_values['speed']) + "/" + str(skj_std.arguments_values['fps']))) # Create sequence of records added to every created frame from math import modf try: # Divide the speed on it's integer and fractional parts speed_fraction = modf(skj_std.arguments_values['speed'])[0] speed_integer = int(modf(skj_std.arguments_values['speed'])[1]) except TypeError as exception_msg: raise TypeError(skj_std.create_error_msg("INTERNAL", exception_msg)) for source_file in skj_std.arguments_values['source']: # Add the sequence to each file's properties source_file['adding_seq'] = create_speed_seq(file_=source_file, int_=speed_integer, frac_=speed_fraction)
def check_time_format(datetime_, ignorable_=True, verbose_=True): ''' Check if string containing date and time is in the specified format. status: finished return: time_struct / None raise: ValueError ''' from time import strptime try: ret = strptime(datetime_[0], datetime_[1]) except (ValueError, TypeError, IndexError) as exception_msg: if skj_std.arguments_values['ignoreerrors'] and ignorable_ == True: skj_std.print_msg_verbose(err_=skj_std.create_error_msg("PYTHON", exception_msg)) return None else: raise ValueError(skj_std.create_error_msg("PYTHON", exception_msg, False)) else: return ret
def check_command_exists(command_, ignorable_=True): ''' Check for command_ existence && executability status: finished return: command_ / None raise: OSError ''' import subprocess try: subprocess.call(command_, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, timeout=5) except (subprocess.TimeoutExpired, subprocess.SubprocessError, OSError, ValueError, TypeError) as exception_msg: if skj_std.arguments_values['ignoreerrors'] and ignorable_ == True: skj_std.print_msg_verbose(err_=skj_std.create_error_msg("PYTHON", exception_msg)) return None else: raise OSError(skj_std.create_error_msg("PYTHON", exception_msg, False)) else: return command_
def check_float_ok(float_, ignorable_=True, verbose_=True): ''' Check if string is float and not inf/nan status: finished return: float / None raise: ValueError ''' from math import isinf, isnan try: if isnan(float(float_)) or isinf(float(float_)): raise ValueError("value is inf/nan in a place where actual number should be") except (ValueError, TypeError) as exception_msg: if skj_std.arguments_values['ignoreerrors'] and ignorable_ == True: skj_std.print_msg_verbose(err_=skj_std.create_error_msg("PYTHON", exception_msg)) return None else: raise ValueError(skj_std.create_error_msg("PYTHON", exception_msg, False)) else: return float(float_)
def create_animation(): ''' Finally, call ffmpeg and let it do it's magic status: finished return: None raise: OSError ''' import os import subprocess from sys import argv if skj_std.arguments_values['name'] == skj_std.arguments_defaults['name']: skj_std.arguments_values['name'] = os.path.split(argv[0])[1] output = os.path.join(os.getcwd(), skj_std.arguments_values['name']) # Output directory if os.path.isdir(output): i = 0 # If the dir already exists ... output = output + '_' + str(i) while os.path.isdir(output): i += 1 # ... try output_i where i = max(i,0) + 1 output = output[:output.rfind('_')] + '_' + str(i) try: os.makedirs(output) # If we do not have write/execute in os.getcwd()... except OSError as exception_msg: if skj_std.arguments_values['ignoreerrors']: skj_std.print_msg_verbose(err_=skj_std.create_error_msg("OUTPUT_DIR_CREATE", output)) output = skj_std.temp_directories['root'] # ... move output to temp dir we already have ... else: # ... or die! raise OSError(skj_std.create_error_msg("OUTPUT_DIR_CREATE", output)) filetype = ".mp4" codec = "libx264" ffmpeg = ["ffmpeg", "-f", "image2", "-r", str(skj_std.arguments_values['fps']), "-i", \ os.path.join(skj_std.temp_directories['gnuplot'], "g_%0" + \ str(len(str(skj_std.arguments_values['frames']))) + "d.png"), "-c:v", codec, "-r", str(skj_std.arguments_values['fps']), \ os.path.join(output, skj_std.arguments_values['name'].split('/')[-1]) + filetype] try: subprocess.check_call(ffmpeg, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) except subprocess.CalledProcessError as exception_msg: raise OSError(skj_std.create_error_msg("PYTHON", exception_msg))
def parse_directives(): ''' Parse configuration file directives status: finished return: None raise: IOError ''' config_file = dict() for argument in skj_std.arguments_repeatable: config_file[argument] = list() try: with open(skj_std.arguments_values['config'], mode="r", encoding="utf-8") as cnf_file: for line in cnf_file: option = line.partition('#')[0].strip().split(None, 1) if len(option) > 0: # Check if it is a valid directive if option[0].lower() not in skj_std.arguments_defaults: raise ValueError(option[0] + " is not a configuration directive") if len(option) == 1: raise ValueError(option[0] + " does not have configuration value") if option[0].lower() in ["speed", "fps", "time"]: # should be created as list of floats from argparse from skj_checker_common import check_float_ok option[1] = check_float_ok(option[1]) # Check && convert string to float if possible # Store valid directives if option[0].lower() in skj_std.arguments_repeatable: config_file[option[0].lower()].append(option[1]) else: config_file[option[0].lower()] = option[1] except (IOError, IndexError, TypeError, ValueError) as exception_msg: if skj_std.arguments_values['ignoreerrors']: skj_std.print_msg_verbose(err_=skj_std.create_error_msg("PYTHON", exception_msg)) return else: raise IOError(skj_std.create_error_msg("PYTHON", exception_msg, False)) else: add_directives_to_args(config_file, skj_std.arguments_repeatable)
def calculate_sfft(): ''' Calculate speed (num of records read each gnuplot iteration), fps, animation duration and num of frames status: devel - those if-chanins should be gone return: None raise: ValueError, ArithmeticError ''' # 0. No user input # 1. User speed && fps # 2. User speed # 3. User fps if (skj_std.arguments_values['time'] == skj_std.arguments_defaults['time'] and\ skj_std.arguments_values['speed'] == skj_std.arguments_defaults['speed'] and\ skj_std.arguments_values['fps'] == skj_std.arguments_defaults['fps']) or\ (skj_std.arguments_values['speed'] != skj_std.arguments_defaults['speed'] and\ skj_std.arguments_values['fps'] != skj_std.arguments_defaults['fps'] and\ skj_std.arguments_values['time'] == skj_std.arguments_defaults['time']) or\ (skj_std.arguments_values['speed'] != skj_std.arguments_defaults['speed'] and\ skj_std.arguments_values['fps'] == skj_std.arguments_defaults['fps'] and\ skj_std.arguments_values['time'] == skj_std.arguments_defaults['time']) or\ (skj_std.arguments_values['speed'] == skj_std.arguments_defaults['speed'] and\ skj_std.arguments_values['fps'] != skj_std.arguments_defaults['fps'] and\ skj_std.arguments_values['time'] == skj_std.arguments_defaults['time']): # Calculate animation time try: skj_std.arguments_values['time'] = skj_std.arguments_values['records'] / \ (skj_std.arguments_values['speed'] * skj_std.arguments_values['fps']) except (ArithmeticError, ZeroDivisionError) as exception_msg: raise ArithmeticError(skj_std.create_error_msg("PYTHON", exception_msg)) # 0. User speed && time # 1. User time elif (skj_std.arguments_values['speed'] != skj_std.arguments_defaults['speed'] and\ skj_std.arguments_values['fps'] == skj_std.arguments_defaults['fps'] and\ skj_std.arguments_values['time'] != skj_std.arguments_defaults['time']) or\ (skj_std.arguments_values['speed'] == skj_std.arguments_defaults['speed'] and\ skj_std.arguments_values['fps'] == skj_std.arguments_defaults['fps'] and\ skj_std.arguments_values['time'] != skj_std.arguments_defaults['time']): # Calculate animation fps try: skj_std.arguments_values['fps'] = skj_std.arguments_values['records'] / \ (skj_std.arguments_values['speed'] * skj_std.arguments_values['time']) except (ArithmeticError, ZeroDivisionError) as exception_msg: raise ArithmeticError(skj_std.create_error_msg("PYTHON", exception_msg)) # User time && fps elif skj_std.arguments_values['speed'] == skj_std.arguments_defaults['speed'] and\ skj_std.arguments_values['fps'] != skj_std.arguments_defaults['fps'] and\ skj_std.arguments_values['time'] != skj_std.arguments_defaults['time']: # Calculate animation speed try: skj_std.arguments_values['speed'] = skj_std.arguments_values['records'] / \ (skj_std.arguments_values['fps'] * skj_std.arguments_values['time']) except (ArithmeticError, ZeroDivisionError) as exception_msg: raise ArithmeticError(skj_std.create_error_msg("PYTHON", exception_msg)) # User time && speed && fps elif skj_std.arguments_values['time'] != skj_std.arguments_defaults['time'] and\ skj_std.arguments_values['speed'] != skj_std.arguments_defaults['speed'] and\ skj_std.arguments_values['fps'] != skj_std.arguments_defaults['fps']: # Calculate correct time try: time_check = skj_std.arguments_values['records'] / \ (skj_std.arguments_values['speed'] * skj_std.arguments_values['fps']) except (ArithmeticError, ZeroDivisionError) as exception_msg: raise ArithmeticError(skj_std.create_error_msg("PYTHON", exception_msg)) # Check if correct time matches user time if time_check != skj_std.arguments_values['time']: if skj_std.arguments_values['ignoreerrors']: skj_std.print_msg_verbose(err_=skj_std.create_error_msg("INVALID_VALUE", \ skj_std.arguments_values['time'])) skj_std.arguments_values['time'] = time_check else: raise ValueError(skj_std.create_error_msg("INVALID_VALUE", skj_std.arguments_values['time'])) from math import ceil skj_std.arguments_values['frames'] = ceil(skj_std.arguments_values['records'] / skj_std.arguments_values['speed'])