Baby Language Lab Scripts
A collection of data processing tools.
 All Classes Namespaces Files Functions Variables Pages
backend_utils.py
Go to the documentation of this file.
1 ## @package utils.backend_utils
2 
3 import re
4 import logging
5 import logging.config
6 import os
7 
8 ## This class contains a collection of static methods for various backend-ish uses. This class should never
9 # be instantiated. Similar UI tools should go in the UIUtils (utils.ui_utils.py) class.
10 class BackendUtils(object):
11  @staticmethod
12  ## Sets up logging for an application.
13  # @param full_log_filename (string) Full path to the log file to use - if the file does not exist, it will be created.
14  def setup_logging(full_log_filename):
15  #create log file if it doesn't exist
16  if not os.path.exists(full_log_filename):
17  logfile = open(full_log_filename, 'w')
18  logfile.close()
19 
20  #set up basic logging
21  logging.basicConfig(level=logging.ERROR,
22  filename=full_log_filename,
23  format='%(asctime)s %(message)s') #prefix each message with a timestamp
24 
25  ## Counts the number of words in a string.
26  # @param text (string) the string to operate upon.
27  # @returns (int) number of words in the string. Hyphens and apostrophies will be converted to spaces before the count is performed, so contractions or hyphenated expressions will count as multiple words (e.g. "can't" => "can t" = 2 words).
28  @staticmethod
29  def get_word_count(text):
30  #strip out any punctuation, replacing it with a space. This means that contractions and hyphonated words will count as two words (as their apostrophy is relaced with a space).
31  text = re.sub(r'[\.\'\"\?\,\!\:;\-\\\/\(\)]', ' ', text)
32 
33  return len(text.split())
34 
35  ## Spilts a given time duration (expressed in seconds) into hours, minutes, and seconds.
36  # @param total_sec (int/float) an amount of time, expressed in seconds
37  # @returns (int, int, int/float) three values representing hours, minutes (< 60), seconds (< 60)
38  @staticmethod
39  def break_time(total_sec):
40  hours = None
41  mins = None
42  secs = None
43  if total_sec != None:
44  #these two lines use the int() function, which will round down to the nearest whole second - the remainder will come out in the secs calculation
45  hours = int(total_sec) / (60 * 60)
46  mins = ( int(total_sec) - (hours * 60 * 60) ) / 60
47  secs = total_sec - (hours * 60 * 60) - (mins * 60) #this may be a float
48 
49  return hours, mins, secs
50 
51  ## Creates a formatted string (suitable for display) from a given time duration (expressed in seconds)
52  # @param total_sec (int/float) an amount of time, expressed in seconds
53  # @param pad_hour_min (boolean=True) Set whether or not to zero-pad hours and minutes placeholders (seconds are always zero-padded)
54  # @param show_hours (boolean=True) Set whether or not to show hours placeholder
55  # @param show_decimals (boolean=True) Set whether or not to show seconds decimal places (if not, seconds are truncated - not rounded!)
56  # @returns (string) a string in the format 'hh:mm:ss.ss'
57  @staticmethod
58  def get_time_str(total_sec, pad_hour_min=True, show_hours=True, show_decimals=True):
59  result = '-'
60  hours, mins, secs = BackendUtils.break_time(total_sec)
61  if hours != None: #if one is valid, all will be
62  #hours placeholder
63  if show_hours:
64  result = ('%02d:' if pad_hour_min else '%d:') % (hours)
65  else:
66  result = ''
67 
68  #minutes placeholder
69  result += ('%02d:' if pad_hour_min else '%d:') % (mins)
70 
71  #seconds placeholder
72  if show_decimals:
73  result += '%s%0.2f' % ('0' if secs < 10 else '', secs)
74  else:
75  result += '%02d' % (int(secs))
76 
77  return result
78 
79  @staticmethod
80  def time_str_to_float(time_str):
81  chunks = time_str.split(':')
82 
83  if len(chunks) > 3: #note: if time_str == '', then the loop below will crash upon trying to convert the chunks[i] to a float
84  raise Exception('Cannot convert time string "%s" to float - invalid format.' % (str(time_str)))
85 
86  result = 0
87  for i in range(len(chunks)):
88  result += float(chunks[i]) * (60.0 ** (len(chunks) - i - 1))
89 
90  return result
91 
92  ## Accepts a string (containing only digits), and prefixes it with a zero if it is < 10
93  # @param num_str (string) an integer in string form
94  # @returns (string) if num_str contains an integer that is less than 10, returns a new string that is num_str prefixed with a zero; otherwise returns num_str
95  @staticmethod
96  def pad_num_str(num_str):
97  return '0%s' % (num_str) if int(num_str) < 10 else num_str
98 
99  ## Converts a date (string) to an integer that's suitable for comparison.
100  # @param date_str (string) date string in the form 'mm/dd/yyyy', followed by an optional space and 'hh:mm'
101  # @returns (int) an integer representing this date - safe to use for comparing dates
102  @staticmethod
103  def _get_date_val(date_str):
104  #format is 'mm/dd/yyyy', then optionally ' hh:mm'
105  parts = re.split(r'[/\s:]', date_str)
106  parts[0], parts[1], parts[2] = parts[2], parts[0], parts[1]
107 
108  date_str = ''
109  for cur_part in parts:
110  date_str += BackendUtils.pad_num_str(cur_part)
111 
112  return int(date_str)
113 
114  ## Checks if a given string contains a float.
115  # @param num_str (string) the string to check
116  # @returns (boolean) True if num_str contains a float, False otherwise
117  @staticmethod
118  def is_float(num_str):
119  result = False
120 
121  #this is not the right way to do it...
122  try:
123  num = float(num_str)
124  result = True
125  except ValueError:
126  pass
127 
128  return result