Skip to content

Commit

Permalink
Merge f750749 into a9ac8e3
Browse files Browse the repository at this point in the history
  • Loading branch information
flxdot committed Jul 26, 2019
2 parents a9ac8e3 + f750749 commit 518e302
Show file tree
Hide file tree
Showing 11 changed files with 138 additions and 111 deletions.
17 changes: 17 additions & 0 deletions pyUnitTypes/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from pathlib import Path
import sys
import inspect
import pkgutil
from importlib import import_module

# make sure to add all dynamically created classes to the modules
# found at: https://www.bnmetrics.com/blog/dynamic-import-in-python3
for (_, name, _) in pkgutil.iter_modules([Path(__file__).parent]):

imported_module = import_module('.' + name, package=__name__)

for i in dir(imported_module):
attribute = getattr(imported_module, i)

if inspect.isclass(attribute):
setattr(sys.modules[__name__], name, attribute)
12 changes: 12 additions & 0 deletions pyUnitTypes/auxiliary.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
def class_factory(BaseClass, name, symbol, to_base, value=float()):
"""Helper function to generically create new classes programmatically."""

# create new local class
class NewClass(BaseClass):
def __init__(self, value=value):
super().__init__(name=name, symbol=symbol, to_base=to_base, value=value)

NewClass.__name__ = name
NewClass.__qualname__ = name

return NewClass
26 changes: 24 additions & 2 deletions pyUnitTypes/basics.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,28 @@
import math
from enum import Enum

SI_PREFIXES = [
('Yotta', 'Y', 1e24),
('Zetta', 'Z', 1e21),
('Exa', 'E', 1e18),
('Peta', 'P', 1e15),
('Tera', 'T', 1e12),
('Giga', 'G', 1e9),
('Mega', 'M', 1e6),
('Kilo', 'K', 1e3),
('Hecto', 'H', 1e2),
('Deca', 'D', 1e1),
('Deci', 'd', 1e-1),
('Centi', 'c', 1e-2),
('Milli', 'm', 1e-3),
('Micro', 'm', 1e-6),
('Nano', 'n', 1e-9),
('Pico', 'p', 1e-12),
('Femto', 'f', 1e-15),
('Atto', 'a', 1e-18),
('Zepto', 'z', 1e-21),
('Yocto', 'y', 1e-24),
]

class System(Enum):
"""Enumeration to switch between unit system. The default system is the metric system."""
Expand Down Expand Up @@ -423,8 +445,8 @@ def __div__(self, other):
self.value /= other
return self
elif issubclass(type(other), BaseUnit):
raise UnknownUnitDivisionError('So far the division of {0} by {1} is unknown.', self.name,
other.name)
raise UnknownUnitDivisionError(
'So far the division of {0} by {1} is unknown.'.format(self.name, other.name))
else:
raise TypeError(
'Can not divide Unit {0} by object of type {1}'.format(self.name, type(other).__name__))
Expand Down
16 changes: 15 additions & 1 deletion pyUnitTypes/current.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from pyUnitTypes.basics import BaseUnit, Conversion
from pyUnitTypes.basics import BaseUnit, Conversion, SI_PREFIXES
from pyUnitTypes.auxiliary import class_factory


class Current(BaseUnit):
Expand Down Expand Up @@ -45,3 +46,16 @@ def __init__(self, value=float()):
"""

super().__init__(name='Ampere', symbol='A', to_base=Conversion(), value=value)


# define all SI derives of lengths
for name, symbol, base10 in SI_PREFIXES:
class_name = '{}Ampere'.format(name)

# generate the new class
generatedClass = class_factory(BaseClass=Current, name='{}A'.format(symbol), symbol=symbol,
to_base=Conversion(base10))
# register the class to the module
globals()[generatedClass.__name__] = generatedClass
# get rid of the temporary stuff
del generatedClass
89 changes: 15 additions & 74 deletions pyUnitTypes/length.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from pyUnitTypes.basics import BaseUnit, Conversion

from pyUnitTypes.basics import BaseUnit, Conversion, SI_PREFIXES
from pyUnitTypes.auxiliary import class_factory

class Length(BaseUnit):
"""
Expand Down Expand Up @@ -32,18 +32,6 @@ def __init__(self, name, symbol, to_base, value, from_base=None):
type(value).__name__))


class KiloMeter(Length):
"""Larger distances in SI units."""

def __init__(self, value=float()):
"""Create instance of the meter class.
:param value: (optional, int or float
"""

super().__init__(name='KiloMeter', symbol='km', to_base=Conversion(1e3), value=value)


class Meter(Length):
"""The base SI unit of lengths."""

Expand All @@ -56,66 +44,6 @@ def __init__(self, value=float()):
super().__init__(name='Meter', symbol='m', to_base=Conversion(), value=value)


class DeciMeter(Length):
"""The measurement only carpenters use."""

def __init__(self, value=float()):
"""Create instance of the meter class.
:param value: (optional, int or float
"""

super().__init__(name='DeciMeter', symbol='dm', to_base=Conversion(1e-1), value=value)


class CentiMeter(Length):
"""The measurement only carpenters use."""

def __init__(self, value=float()):
"""Create instance of the meter class.
:param value: (optional, int or float
"""

super().__init__(name='CentiMeter', symbol='cm', to_base=Conversion(1e-2), value=value)


class MilliMeter(Length):
"""The unit for every one building something from metal"""

def __init__(self, value=float()):
"""Create instance of the meter class.
:param value: (optional, int or float
"""

super().__init__(name='MilliMeter', symbol='mm', to_base=Conversion(1e-3), value=value)


class MicroMeter(Length):
"""That's small."""

def __init__(self, value=float()):
"""Create instance of the meter class.
:param value: (optional, int or float
"""

super().__init__(name='MicroMeter', symbol='μm', to_base=Conversion(1e-6), value=value)


class NanoMeter(Length):
"""That's so small that light color changes with it."""

def __init__(self, value=float()):
"""Create instance of the meter class.
:param value: (optional, int or float
"""

super().__init__(name='NanoMeter', symbol='nm', to_base=Conversion(1e-9), value=value)


class Mile(Length):
"""Distances on US highways"""

Expand Down Expand Up @@ -162,3 +90,16 @@ def __init__(self, value=float()):
"""

super().__init__(name='Inch', symbol='inch', to_base=Conversion(0.0254), value=value)


# define all SI derives of lengths
for name, symbol, base10 in SI_PREFIXES:
class_name = '{}Meter'.format(name)

# generate the new class
generatedClass = class_factory(BaseClass=Length, name=class_name, symbol='{}m'.format(symbol),
to_base=Conversion(base10))
# register the class to the module
globals()[generatedClass.__name__] = generatedClass
# get rid of the temporary stuff
del generatedClass
17 changes: 15 additions & 2 deletions pyUnitTypes/luminous.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from pyUnitTypes.basics import BaseUnit, Conversion
from pyUnitTypes.basics import BaseUnit, Conversion, SI_PREFIXES
from pyUnitTypes.auxiliary import class_factory


class Luminous(BaseUnit):
Expand Down Expand Up @@ -43,4 +44,16 @@ def __init__(self, value=float()):
:param value: (optional, int or float) the amount of Candela
"""

super().__init__(name='Candela', symbol='cd', to_base=Conversion(), value=value)
super().__init__(name='Candela', symbol='cd', to_base=Conversion(), value=value)


# define all SI derives of lengths
for name, symbol, base10 in SI_PREFIXES:
class_name = '{}Candela'.format(name)

# generate the new class
generatedClass = class_factory(BaseClass=Luminous, name=class_name, symbol=symbol, to_base=Conversion(base10))
# register the class to the module
globals()[generatedClass.__name__] = generatedClass
# get rid of the temporary stuff
del generatedClass
48 changes: 22 additions & 26 deletions pyUnitTypes/mass.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from pyUnitTypes.basics import Conversion, BaseUnit
import sys
from pyUnitTypes.basics import BaseUnit, Conversion, SI_PREFIXES
from pyUnitTypes.auxiliary import class_factory


class Mass(BaseUnit):
Expand Down Expand Up @@ -65,31 +67,7 @@ def __init__(self, value=float()):
:param value: (optional, int or float) the amount of days
"""

super().__init__(name='KiloGram', symbol='kg', to_base=Conversion(1e-3), value=value)


class MilliGram(Mass):
"""That's not really much."""

def __init__(self, value=float()):
"""Create instance of the Tonne class.
:param value: (optional, int or float) the amount of days
"""

super().__init__(name='MilliGram', symbol='mg', to_base=Conversion(1e-6), value=value)


class MicroGram(Mass):
"""That's not really much."""

def __init__(self, value=float()):
"""Create instance of the Tonne class.
:param value: (optional, int or float) the amount of days
"""

super().__init__(name='MicroGram', symbol='μg', to_base=Conversion(1e-9), value=value)
super().__init__(name='KiloGram', symbol='g', to_base=Conversion(1e-3), value=value)


class Pound(Mass):
Expand Down Expand Up @@ -138,3 +116,21 @@ def __init__(self, value=float()):
"""

super().__init__(name='ShortTon', symbol='ton (US)', to_base=Conversion(907.1847), value=value)


# define all SI derives of lengths
for name, symbol, base10 in SI_PREFIXES:
if name == 'Kilo':
continue
class_name = '{}Gram'.format(name)

# account for the fact that kilogram is the base unit of the mass
base10 /= 1e3

# generate the new class
generatedClass = class_factory(BaseClass=Mass, name=class_name, symbol='{}g'.format(symbol),
to_base=Conversion(base10))
# register the class to the module
globals()[generatedClass.__name__] = generatedClass
# get rid of the temporary stuff
del generatedClass
17 changes: 15 additions & 2 deletions pyUnitTypes/substance.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from pyUnitTypes.basics import BaseUnit, Conversion
from pyUnitTypes.basics import BaseUnit, Conversion, SI_PREFIXES
from pyUnitTypes.auxiliary import class_factory


class Substance(BaseUnit):
Expand Down Expand Up @@ -44,4 +45,16 @@ def __init__(self, value=float()):
:param value: (optional, int or float) the amount of Moles
"""

super().__init__(name='Mole', symbol='mol', to_base=Conversion(), value=value)
super().__init__(name='Mole', symbol='mol', to_base=Conversion(), value=value)


for name, symbol, base10 in SI_PREFIXES:
class_name = '{}Mole'.format(name)

# generate the new class
generatedClass = class_factory(BaseClass=Substance, name='{}mol'.format(symbol), symbol=symbol,
to_base=Conversion(base10))
# register the class to the module
globals()[generatedClass.__name__] = generatedClass
# get rid of the temporary stuff
del generatedClass
2 changes: 1 addition & 1 deletion pyUnitTypes/time.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def __init__(self, name, symbol, to_base, value, from_base=None):


class Day(Time):
"""A day. You know. / of those and you'll have a week."""
"""A day. You know. 7 of those and you'll have a week."""

def __init__(self, value=float()):
"""Create instance of the Day class.
Expand Down
3 changes: 1 addition & 2 deletions tests/test_length.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from unittest import TestCase

from pyUnitTypes.length import KiloMeter, Meter, DeciMeter, CentiMeter, MilliMeter, MicroMeter, NanoMeter, Mile, Yard, \
Feet, Inch
from pyUnitTypes.length import *
from pyUnitTypes.temperature import Celsius


Expand Down
2 changes: 1 addition & 1 deletion tests/test_mass.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from unittest import TestCase

from pyUnitTypes.length import Meter
from pyUnitTypes.mass import KiloGram, Gram, MicroGram, MilliGram, Pound, Ton, Tonne, ShortTon, Ounce
from pyUnitTypes.mass import *


class TestTimes(TestCase):
Expand Down

0 comments on commit 518e302

Please sign in to comment.