Merge branch 'packaging' v2.0.0
authorAlexander Vasarab <alexander@wylark.com>
Sun, 21 Jun 2020 02:28:53 +0000 (19:28 -0700)
committerAlexander Vasarab <alexander@wylark.com>
Sun, 21 Jun 2020 02:28:53 +0000 (19:28 -0700)
.gitignore [new file with mode: 0644]
README [deleted file]
README.md [new file with mode: 0644]
munter.py
munter/__init__.py [new file with mode: 0755]
munter/__main__.py [new file with mode: 0644]
munter/munter.py [new file with mode: 0644]
setup.py [new file with mode: 0644]
tests/test.py [new file with mode: 0755]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..f98771d
--- /dev/null
@@ -0,0 +1,16 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# Distribution / packaging
+build/
+dist/
+wheels/
+*.egg-info/
+*.egg
+MANIFEST
+
+# Environments
+env/
+venv/
diff --git a/README b/README
deleted file mode 100644 (file)
index fe396e9..0000000
--- a/README
+++ /dev/null
@@ -1,59 +0,0 @@
-=========
-Munter.py
-=========
-
-Helps you speed up your tour and trip planning.
-
-Disclaimer
-==========
-
-The time calculations produced by this program are not guaranteed to be
-accurate. Any harm or hazard encountered due to blindly trusting these
-estimates is your own fault.
-
-Installation
-============
-
-There is no installation and there are no dependencies external to the Python
-standard library.
-
-How to use it
-=============
-
-./munter.py --help
-
-My workflow involves planning my tour using tools like ArcGIS or CalTopo. Then,
-I take the stats between each leg (distance, vertical gain/loss) of the tour
-and run them through Munter.py and thence record its output to my field
-notebook.
-
-The rudimentary "GUI" can be directly transferred to e.g. the format used by
-SnowPit Technologies' "Avalanche Field Notebook" or your own personal format
-(e.g. RitR No. 471).
-
-Future plans
-============
-
-* Personal "fitness" switch (to help fine tune your estimates based on
-                                                        your personal fitness level as observed
-                                                        over time)
-* GTK mode
-* Use as a Python library from within another project
-* Lint it (e.g. therapist)
-* Pip?
-
-Version History
-===============
-
-1.0.2 (Jun 2020)
-  * A few small bugfixes.
-
-1.0.1 (Jun 2020)
-  * Add LICENSE and README.
-
-1.0.0 (Jun 2020)
-  * First released version. Includes sensible defaults and a rudimentary CLI
-    "GUI".
-
-pre-1.0.0 (Mar 2017)
-  * In use privately/internally since 2017.
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..a61f2d9
--- /dev/null
+++ b/README.md
@@ -0,0 +1,67 @@
+Munter.py
+=========
+
+Helps you speed up your tour and trip planning.
+
+Disclaimer
+----------
+
+The time calculations produced by this program are not guaranteed to be
+accurate. Any harm or hazard encountered due to blindly trusting these
+estimates is your own fault.
+
+Installation
+------------
+
+There is no installation and there are no dependencies external to the Python
+standard library.
+
+How to use it
+-------------
+
+`./munter.py --help`
+
+My workflow involves planning my tour using tools like ArcGIS or CalTopo. Then,
+I take the stats between each leg (distance, vertical gain/loss) of the tour
+and run them through Munter.py and thence record its output to my field
+notebook.
+
+The rudimentary "GUI" can be directly transferred to e.g. the format used by
+SnowPit Technologies' "Avalanche Field Notebook" or your own personal format
+(e.g. RitR No. 471).
+
+Future plans
+------------
+
+* Personal "fitness" switch (to help fine tune your estimates based on
+                                                        your personal fitness level as observed
+                                                        over time)
+* GTK mode
+* Use as a Python library from within another project
+* Lint it (e.g. therapist)
+* Pip?
+* Sphinx/autodoc?
+
+Version History
+---------------
+
+- 2.0.0 (Jun 2020)
+
+  Packaged for distribution as a standalone program (and library).
+
+- 1.0.2 (Jun 2020)
+
+  A few small bugfixes.
+
+- 1.0.1 (Jun 2020)
+
+  Add LICENSE and README.
+
+- 1.0.0 (Jun 2020)
+
+  First released version. Includes sensible defaults and a rudimentary CLI
+  "GUI".
+
+- pre-1.0.0 (Mar 2017)
+
+  In use privately/internally since 2017.
index 2ee36d4757a443e3a14b6a92328a2cbc19f926d7..485db199db167ba88417ff8a733c56a3330aee7f 100755 (executable)
--- a/munter.py
+++ b/munter.py
@@ -1,142 +1,9 @@
 #! /usr/bin/env python
 # -*- coding: utf-8 -*-
 
-
-"""
-Munter Time Calculation
-Alexander Vasarab
-Wylark Mountaineering LLC
-
-Version 1.0.2
-
-A rudimentary program which implements the Munter time calculation.
-"""
-
+"""Wrapper for running directly from the source code directory"""
 import sys
-import argparse
-
-class InvalidUnitsException(Exception):
-    pass
-
-rates = {
-    'uphill': { 'rate': 4, 'direction': '↑' },
-    'flat': { 'rate': 6, 'direction': '→' }, # or downhill on foot
-    'downhill': { 'rate': 10, 'direction': '↓' },
-    'bushwhacking': { 'rate': 2, 'direction': '↹' },
-}
-
-unit_choices = ['metric', 'imperial']
-travel_mode_choices = rates.keys()
-
-def time_calc(distance, elevation, rate, units):
-    retval = {}
-
-    if units not in unit_choices:
-        raise InvalidUnitsException
-
-    unit_count = 0
-
-    if 'imperial' == units:
-        # 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['unit_count'] = unit_count
-    retval['direction'] = rates[rate]['direction']
-    retval['pace'] = rates[rate]['rate']
-
-    return retval
-
-def print_ugly_estimate(est):
-    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)))
-
-def print_pretty_estimate(est):
-    hours = int(est['time'])
-    minutes = int((est['time'] - hours) * 60)
-
-    # NOTE: Below, the line with the unicode up arrow uses an alignment
-    #       value of 31. In the future, consider using e.g. wcwidth
-    #       library so that this is more elegant.
-    print("\n\t╒═══════════════════════════════╕")
-    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'])))
-    print("\t╎▒{human_time:^29}▒╎│".format(
-            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():
-    parser = argparse.ArgumentParser(description='Munter Time Calculation')
-
-    parser.add_argument('--distance',
-        '-d',
-        type=float,
-        required=True,
-        help='Distance (in km, by default)')
-
-    parser.add_argument('--elevation',
-        '-e',
-        type=float,
-        required=True,
-        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 (flat, by default)')
-
-    parser.add_argument('--units',
-        '-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);
-
-    return parser
-
-def main():
-    parser = get_parser()
-    opts = parser.parse_args()
-
-    distance = opts.distance
-    elevation = opts.elevation
-    units = opts.units
-    travel_mode = opts.travel_mode
-
-    time_estimate = time_calc(distance, elevation, travel_mode, units=units)
-
-    if opts.pretty:
-        print_pretty_estimate(time_estimate)
-    else:
-        print_ugly_estimate(time_estimate)
-
-    return 0
+from munter.munter import main
 
 if __name__ == "__main__":
     sys.exit(main())
diff --git a/munter/__init__.py b/munter/__init__.py
new file mode 100755 (executable)
index 0000000..3f73639
--- /dev/null
@@ -0,0 +1,3 @@
+"""Main package for Munter.py"""
+__version__ = "2.0.0"
+from .munter import time_calc
diff --git a/munter/__main__.py b/munter/__main__.py
new file mode 100644 (file)
index 0000000..389c8a2
--- /dev/null
@@ -0,0 +1,7 @@
+# -*- coding: utf-8 -*-
+
+"""entry point for program and library"""
+
+from .munter import main
+main()
+
diff --git a/munter/munter.py b/munter/munter.py
new file mode 100644 (file)
index 0000000..7179e52
--- /dev/null
@@ -0,0 +1,139 @@
+# -*- coding: utf-8 -*-
+
+
+"""
+Munter Time Calculation
+Alexander Vasarab
+Wylark Mountaineering LLC
+
+A rudimentary program which implements the Munter time calculation.
+"""
+
+import sys
+import argparse
+
+class InvalidUnitsException(Exception):
+    pass
+
+rates = {
+    'uphill': { 'rate': 4, 'direction': '↑' },
+    'flat': { 'rate': 6, 'direction': '→' }, # or downhill on foot
+    'downhill': { 'rate': 10, 'direction': '↓' },
+    'bushwhacking': { 'rate': 2, 'direction': '↹' },
+}
+
+unit_choices = ['metric', 'imperial']
+travel_mode_choices = rates.keys()
+
+def time_calc(distance, elevation, rate, units):
+    retval = {}
+
+    if units not in unit_choices:
+        raise InvalidUnitsException
+
+    unit_count = 0
+
+    if 'imperial' == units:
+        # 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['unit_count'] = unit_count
+    retval['direction'] = rates[rate]['direction']
+    retval['pace'] = rates[rate]['rate']
+
+    return retval
+
+def print_ugly_estimate(est):
+    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)))
+
+def print_pretty_estimate(est):
+    hours = int(est['time'])
+    minutes = int((est['time'] - hours) * 60)
+
+    # NOTE: Below, the line with the unicode up arrow uses an alignment
+    #       value of 31. In the future, consider using e.g. wcwidth
+    #       library so that this is more elegant.
+    print("\n\t╒═══════════════════════════════╕")
+    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'])))
+    print("\t╎▒{human_time:^29}▒╎│".format(
+            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():
+    parser = argparse.ArgumentParser(description='Munter Time Calculation')
+
+    parser.add_argument('--distance',
+        '-d',
+        type=float,
+        required=True,
+        help='Distance (in km, by default)')
+
+    parser.add_argument('--elevation',
+        '-e',
+        type=float,
+        required=True,
+        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 (flat, by default)')
+
+    parser.add_argument('--units',
+        '-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);
+
+    return parser
+
+def main():
+    parser = get_parser()
+    opts = parser.parse_args()
+
+    distance = opts.distance
+    elevation = opts.elevation
+    units = opts.units
+    travel_mode = opts.travel_mode
+
+    time_estimate = time_calc(distance, elevation, travel_mode, units=units)
+
+    if opts.pretty:
+        print_pretty_estimate(time_estimate)
+    else:
+        print_ugly_estimate(time_estimate)
+
+    return 0
+
+if __name__ == "__main__":
+    sys.exit(main())
diff --git a/setup.py b/setup.py
new file mode 100644 (file)
index 0000000..f30ca70
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+"""munter.py distutils configuration."""
+import os
+import re
+from setuptools import setup
+
+cur_dir = os.path.dirname(__file__)
+version = re.search(
+    '^__version__\s*=\s*"(.*)"',
+    open(os.path.join(cur_dir, 'munter/__init__.py')).read(),
+    re.M
+    ).group(1)
+
+with open(os.path.join(cur_dir, 'README.md'), encoding='utf-8') as readme_file:
+    readme = readme_file.read()
+
+setup(
+    name='munter.py',
+    version=version,
+    description=(
+        'An easy-to-use implementation of the Munter time calculation'
+    ),
+    long_description=readme,
+    long_description_content_type='text/markdown',
+    author='Alexander Vasarab',
+    author_email='alexander@wylark.com',
+    url='https://wylark.com/munter',
+    packages=['munter'],
+    package_dir={'munter': 'munter'},
+    entry_points={'console_scripts': ['munter = munter.munter:main']},
+    include_package_data=True,
+    python_requires='>=3.6',
+    license='ISC',
+    classifiers=[
+        "Development Status :: 5 - Production/Stable",
+        "Environment :: Console",
+        "Intended Audience :: Other Audience",
+        "Intended Audience :: Developers",
+        "Natural Language :: English",
+        "License :: OSI Approved :: ISC License (ISCL)",
+        "Programming Language :: Python :: 3 :: Only",
+        "Programming Language :: Python :: 3",
+        "Programming Language :: Python :: 3.6",
+        "Programming Language :: Python :: 3.7",
+        "Programming Language :: Python :: 3.8",
+        "Programming Language :: Python",
+        "Topic :: Software Development",
+        "Topic :: Software Development :: Libraries :: Python Modules",
+    ],
+    keywords=[
+        "munter",
+        "tour planning",
+        "trip planning",
+        "time estimate",
+    ],
+)
diff --git a/tests/test.py b/tests/test.py
new file mode 100755 (executable)
index 0000000..bf5b01b
--- /dev/null
@@ -0,0 +1,6 @@
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+import munter
+
+est = munter.time_calc(3.2, 2300, 'uphill', 'imperial')
+print("Time Estimate: %s hours" % est['time'])