Merge branch 'release-2.3.0'
[munter.git] / munter / munter.py
index d8683491f2bd899aa08e1baea82697c935ca547a..062e6769edd12ac0556435aaace0d5186b35afe7 100644 (file)
@@ -16,59 +16,63 @@ from . import __progname__ as progname
 from . import __version__ as version
 
 class InvalidUnitsException(Exception):
-    pass
+    """Exception class for when invalid units are specified"""
 
-rates = {
-    'uphill': { 'rate': 4, 'direction': '↑' },
-    'flat': { 'rate': 6, 'direction': '→' }, # or downhill on foot
-    'downhill': { 'rate': 10, 'direction': '↓' },
-    'bushwhacking': { 'rate': 2, 'direction': '↹' },
+RATES = {
+    'uphill': {'rate': 4, 'direction': '↑'},
+    'flat': {'rate': 6, 'direction': '→'}, # or downhill on foot
+    'downhill': {'rate': 10, 'direction': '↓'},
+    'bushwhacking': {'rate': 2, 'direction': '↹'},
 }
 
-fitnesses = {
+FITNESSES = {
     'slow': 1.2,
     'average': 1,
     'fast': .7,
 }
 
-unit_choices = ['metric', 'imperial']
-travel_mode_choices = rates.keys()
-fitness_choices = fitnesses.keys()
+UNIT_CHOICES = ['metric', 'imperial']
+TRAVEL_MODE_CHOICES = RATES.keys()
+FITNESS_CHOICES = FITNESSES.keys()
 
 def time_calc(distance, elevation, fitness='average', rate='uphill',
-    units='imperial'):
+              units='imperial'):
+    """
+    the heart of the program, the Munter time calculation implementation
+    """
     retval = {}
 
-    if units not in unit_choices:
+    if units not in UNIT_CHOICES:
         raise InvalidUnitsException
 
     unit_count = 0
 
-    if 'imperial' == units:
+    if units == 'imperial':
         # convert to metric
         distance = (distance * 1.609) # mi to km
         elevation = (elevation * .305) # ft to m
 
     unit_count = distance + (elevation / 100.0)
 
-    retval['time'] = (distance + (elevation / 100.0)) / rates[rate]['rate']
-    retval['time'] = retval['time'] * fitnesses[fitness]
+    retval['time'] = (distance + (elevation / 100.0)) / RATES[rate]['rate']
+    retval['time'] = retval['time'] * FITNESSES[fitness]
 
     retval['unit_count'] = unit_count
-    retval['direction'] = rates[rate]['direction']
-    retval['pace'] = rates[rate]['rate']
+    retval['direction'] = RATES[rate]['direction']
+    retval['pace'] = RATES[rate]['rate']
 
     return retval
 
 def print_ugly_estimate(est):
+    """plain-jane string containing result"""
     hours = int(est['time'])
     minutes = int((est['time'] - hours) * 60)
     print("{human_time}".format(
-            human_time="{hours} hours {minutes} minutes".format(
-                hours=hours,
-                minutes=minutes)))
+        human_time="{hours} hours {minutes} minutes".format(
+            hours=hours, minutes=minutes)))
 
 def print_pretty_estimate(est):
+    """more elaborate, console-based 'GUI' displaying result"""
     hours = int(est['time'])
     minutes = int((est['time'] - hours) * 60)
 
@@ -79,84 +83,86 @@ def print_pretty_estimate(est):
     print("\t╎▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒╎╮")
     print("\t╎▒{:^29}▒╎│".format(''))
     print("\t╎▒{pace_readable:^31}▒╎│".format(
-            pace_readable="{units} {direction} @ {pace}".format(
-                units=round(est['unit_count']),
-                direction=est['direction'],
-                pace=est['pace'])))
+        pace_readable="{units} {direction} @ {pace}".format(
+            units=round(est['unit_count']),
+            direction=est['direction'],
+            pace=est['pace'])))
     print("\t╎▒{human_time:^29}▒╎│".format(
-            human_time="{hours} hours {minutes} minutes".format(
-                hours=hours,
-                minutes=minutes)))
+        human_time="{hours} hours {minutes} minutes".format(
+            hours=hours,
+            minutes=minutes)))
     print("\t╎▒{:^29}▒╎│".format(''))
     print("\t╎▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒╎│")
     print("\t╘═══════════════════════════════╛│")
     print("\t └───────────────────────────────┘\n")
 
 def get_parser():
+    """return ArgumentParser for this program"""
     parser = argparse.ArgumentParser(description='Implementation of '
-        'the Munter time calculation')
+                                     'the Munter time calculation')
 
     # No required args anymore, since -g overrides any requirement
     parser.add_argument('--distance',
-        '-d',
-        default=0.0,
-        type=float,
-        required=False,
-        help='Distance (in km, by default)')
+                        '-d',
+                        default=0.0,
+                        type=float,
+                        required=False,
+                        help='Distance (in km, by default)')
 
     parser.add_argument('--elevation',
-        '-e',
-        default=0.0,
-        type=float,
-        required=False,
-        help='Elevation change (in m, by default)')
+                        '-e',
+                        default=0.0,
+                        type=float,
+                        required=False,
+                        help='Elevation change (in m, by default)')
 
     parser.add_argument('--travel-mode',
-        '-t',
-        type=str,
-        default='uphill',
-        choices=travel_mode_choices, required=False,
-        help='Travel mode (uphill, by default)')
+                        '-t',
+                        type=str,
+                        default='uphill',
+                        choices=TRAVEL_MODE_CHOICES, required=False,
+                        help='Travel mode (uphill, by default)')
 
     parser.add_argument('--fitness',
-        '-f',
-        type=str,
-        default='average',
-        choices=fitness_choices, required=False,
-        help='Fitness modifier (average, by default)')
+                        '-f',
+                        type=str,
+                        default='average',
+                        choices=FITNESS_CHOICES, required=False,
+                        help='Fitness modifier (average, by default)')
 
     parser.add_argument('--units',
-        '-u',
-        type=str,
-        default='imperial',
-        required=False,
-        choices=unit_choices,
-        help='Units of input values')
+                        '-u',
+                        type=str,
+                        default='imperial',
+                        required=False,
+                        choices=UNIT_CHOICES,
+                        help='Units of input values')
 
     parser.add_argument('--pretty',
-        '-p',
-        action='store_true',
-        default=False,
-        required=False,
-        help="Make output pretty");
+                        '-p',
+                        action='store_true',
+                        default=False,
+                        required=False,
+                        help='Make output pretty')
 
     parser.add_argument('--gui',
-        '-g',
-        action='store_true',
-        default=False,
-        required=False,
-        help='Launch GUI mode (overrides --pretty)')
+                        '-g',
+                        action='store_true',
+                        default=False,
+                        required=False,
+                        help='Launch GUI mode (overrides --pretty)')
 
     parser.add_argument('--version',
-        '-v',
-        action='store_true',
-        default=False,
-        required=False,
-        help='Print version and exit')
+                        '-v',
+                        action='store_true',
+                        default=False,
+                        required=False,
+                        help='Print version and exit')
 
     return parser
 
 def main():
+    """main routine: sort through args, decide what to do"""
     parser = get_parser()
     opts = parser.parse_args()
 
@@ -174,7 +180,12 @@ def main():
         return 0
 
     time_estimate = time_calc(distance=distance, elevation=elevation,
-        fitness=fitness, rate=travel_mode, units=units)
+                              fitness=fitness, rate=travel_mode,
+                              units=units)
+
+    # auto-start in GUI mode if the program is not invoked from terminal
+    if len(sys.argv) == 1 and not sys.stdin.isatty():
+        gui = True
 
     if gui:
         from . import gui