Skip to content

Commit

Permalink
Switch to Decimal based values
Browse files Browse the repository at this point in the history
  • Loading branch information
codingjoe committed Apr 18, 2020
1 parent 43b2438 commit 0978a66
Show file tree
Hide file tree
Showing 50 changed files with 1,581 additions and 1,640 deletions.
2 changes: 2 additions & 0 deletions .bandit
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[bandit]
exclude: tests
18 changes: 18 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# http://editorconfig.org

root = true

[*]
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
insert_final_newline = true
charset = utf-8
end_of_line = lf
max_line_length = 88

[*.{json,yml,yaml}]
indent_size = 2

[LICENSE]
insert_final_newline = false
23 changes: 16 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,31 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-python@v1
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- run: python -m pip install isort
- run: isort --check-only --diff --recursive .

flake8:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-python@v1
- uses: actions/checkout@v2
- run: python -m pip install flake8
- run: flake8 .

pydocstyle:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-python@v1
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- run: python -m pip install pydocstyle
- run: pydocstyle .

black:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-python@v1
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- run: python -m pip install black
- run: black --check --diff .

Expand All @@ -36,22 +44,23 @@ jobs:
- isort
- pydocstyle
- black
- flake8
strategy:
matrix:
os:
- ubuntu-latest
- windows-latest
- macos-latest
python-version:
- 3.5
- 3.6
- 3.7
- 3.8
runs-on: ${{ matrix.os }}
steps:
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1.1.1
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- run: python -m pip install --upgrade setuptools wheel codecov
- run: python setup.py test
- run: codecov
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ include/
lib/
docs/_build/
.coverage
htmlcov/
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2014 Adam Coddington
Copyright (c) 2020 Johannes Hoppe

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
113 changes: 72 additions & 41 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,55 +1,86 @@
.. image:: https://travis-ci.org/coddingtonbear/python-measurement.svg?branch=master
:target: https://travis-ci.org/coddingtonbear/python-measurement
==================
Python measurement
==================

Easily use and manipulate unit-aware measurement objects in Python.
**High precision unit-aware measurement objects in Python.**

`django.contrib.gis.measure <https://github.com/django/django/blob/master/django/contrib/gis/measure.py>`_
has these wonderful 'Distance' objects that can be used not only for storing a
unit-aware distance measurement, but also for converting between different
units and adding/subtracting these objects from one another.
>>> from measurement import measures
>>> measures.Distance("12 megaparsec")["British yard"]
Decimal('404948208659679393828910.8771')

This module not only provides those Distance and Area measurement
objects, but also other measurements including:
This package provides a large reference collection of various measure and
their corresponding SI (Metric), US or Imperial units. Its high precision
supports use cases all the way from quantum mechanics to astrophysics.

- Energy
- Speed
- Temperature
- Time
- Volume
- Weight
- Documentation for python-measurement is available an
`ReadTheDocs <https://python-measurement.readthedocs.org/>`_.
- Please post issues on
`Github <https://github.com/coddingtonbear/python-measurement/issues>`_.

Example:
Installation
============

.. code-block:: python
You can install the latest version of the package with Pip::

>>> from measurement.measures import Weight
>>> weight_1 = Weight(lb=125)
>>> weight_2 = Weight(kg=40)
>>> added_together = weight_1 + weight_2
>>> added_together
Weight(lb=213.184976807)
>>> added_together.kg # Maybe I actually need this value in kg?
96.699
python3 -m pip install measurement

.. warning::
Measurements are stored internally by converting them to a
floating-point number of a (generally) reasonable SI unit. Given that
floating-point numbers are very slightly lossy, you should be aware of
any inaccuracies that this might cause.
Usage
=====

TLDR: Do not use this in
`navigation algorithms guiding probes into the atmosphere of extraterrestrial worlds <http://en.wikipedia.org/wiki/Mars_Climate_Orbiter>`_.
Using Measurement Objects
-------------------------

- Documentation for python-measurement is available an
`ReadTheDocs <https://python-measurement.readthedocs.org/>`_.
- Please post issues on
`Github <https://github.com/coddingtonbear/python-measurement/issues>`_.
- Test status available on
`Travis-CI <https://travis-ci.org/coddingtonbear/python-measurement>`_.
You can import any of the above measures from `measurement.measures`
and use it for easily handling measurements like so:

>>> from measurement.measures import Mass
>>> m = Mass(lb=135) # Represents 135 lbs
>>> print(m)
135 lb
>>> print(m["long ton"])
0.06027063971456692913385826772

You can create a measurement unit using any compatible unit and can transform
it into any compatible unit. See :doc:`measures` for information about which
units are supported by which measures.

.. seealso::
Should you be planing to go to Mars, you might need to increase your
`decimal precision`_, like so:

>>> import decimal
>>> decimal.getcontext().prec = 28

.. _decimal precision: https://docs.python.org/3.8/library/decimal.html

Guessing Measurements
---------------------

If you happen to be in a situation where you are processing a list of
value/unit pairs (like you might find at the beginning of a recipe), you can
use the `guess` function to give you a measurement object.:

>>> from measurement.utils import guess
>>> m = guess(10, "mg")
>>> print(repr(m))
Mass(gram="0.010")

By default, this will check all built-in measures, and will return the first
measure having an appropriate unit. You may want to constrain the list of
measures checked (or your own measurement classes, too) to make sure
that your measurement is not mis-guessed, and you can do that by specifying
the ``measures`` keyword argument:

>>> from measurement.measures import Distance, Temperature, Volume
>>> m = guess(24, "°F", measures=[Distance, Volume, Temperature])
>>> print(repr(m))
Temperature(fahrenheit="24.00000000000000000000000008")

.. image:: https://d2weczhvl823v0.cloudfront.net/coddingtonbear/python-measurement/trend.png
:alt: Bitdeli badge
:target: https://bitdeli.com/free
If no match is found, a :class:`ValueError` exception will be raised.

.. note::
It is absolutely possible for this to misguess due to common measurement
abbreviations overlapping -- for example, both Temperature and Energy
accept the argument ``c`` for representing degrees celsius and calories
respectively. It is advisible that you constrain the list of measurements
to check to ones that you would consider appropriate for your input data.
101 changes: 101 additions & 0 deletions docs/caliper.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 29 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,49 @@
"""Sphinx configuration file."""
import inspect

from pkg_resources import get_distribution

from measurement.base import AbstractMeasure

project = "python-measurement"
copyright = "2013, Adam Coddington"
copyright = "2020, Johannes Hoppe"
release = get_distribution("measurement").version
version = ".".join(release.split(".")[:2])
html_theme = "python_docs_theme"

master_doc = "index"

html_logo = "caliper.svg"

extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.viewcode",
"sphinx.ext.napoleon",
"sphinx.ext.intersphinx",
"sphinx.ext.doctest",
"sphinx.ext.inheritance_diagram",
]

intersphinx_mapping = {
"python": ("https://docs.python.org/3", None),
}

inheritance_graph_attrs = dict(rankdir="TB")

graphviz_output_format = "svg"

autodoc_member_order = "bysource"


def process_measures(app, what, name, obj, options, lines):
if inspect.isclass(obj) and issubclass(obj, AbstractMeasure):
lines.append("**Supported Units:**")
lines.extend(
f" :{obj._attr_to_unit(name)}: {', '.join(value.symbols)}"
for name, value in obj._org_units.items()
)
return lines


def setup(app):
app.connect("autodoc-process-docstring", process_measures)
12 changes: 12 additions & 0 deletions docs/custom_measures.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Custom Measures
===============

API reference
-------------

.. inheritance-diagram:: measurement.base

.. automodule:: measurement.base
:show-inheritance:
:members:
:inherited-members:
Loading

0 comments on commit 0978a66

Please sign in to comment.