From a54992e59aa0ef2d4ac54cc1bd7af5a007121369 Mon Sep 17 00:00:00 2001 From: "Andrew K. Milton" Date: Sun, 5 Dec 2021 09:01:25 -0800 Subject: [PATCH] [akm] Clean Up * Add more typing information * Tidy up imports * PEP-8 naming --- README.md | 6 +- quantity/PyQuantity.egg-info/PKG-INFO | 13 ++++ quantity/PyQuantity.egg-info/SOURCES.txt | 14 ++++ .../PyQuantity.egg-info/dependency_links.txt | 1 + quantity/PyQuantity.egg-info/top_level.txt | 2 + quantity/bit_field/bit_field.py | 18 ++--- quantity/prefix/__init__.py | 1 - quantity/prefix/prefix.py | 9 +-- quantity/prefix/prefixes.py | 1 - quantity/quantity/quantity.py | 28 ++++---- .../quantity_config_parser.py | 68 +++++++++---------- quantity/unit/__init__.py | 3 +- quantity/unit/unit.py | 42 ++++++------ quantity/unit/units.py | 4 +- setup.py | 2 +- .../Test.ini => tests/TestData/test.ini | 0 tests/__init__.py | 0 {test => tests}/test_prefix.py | 0 {test => tests}/test_quantity.py | 0 .../test_quantity_config_parser.py | 0 {test => tests}/test_unit.py | 17 ++--- 21 files changed, 124 insertions(+), 105 deletions(-) create mode 100644 quantity/PyQuantity.egg-info/PKG-INFO create mode 100644 quantity/PyQuantity.egg-info/SOURCES.txt create mode 100644 quantity/PyQuantity.egg-info/dependency_links.txt create mode 100644 quantity/PyQuantity.egg-info/top_level.txt rename test/TestData/Test.ini => tests/TestData/test.ini (100%) create mode 100644 tests/__init__.py rename {test => tests}/test_prefix.py (100%) rename {test => tests}/test_quantity.py (100%) rename {test => tests}/test_quantity_config_parser.py (100%) rename {test => tests}/test_unit.py (74%) diff --git a/README.md b/README.md index 48debc4..9ab466b 100644 --- a/README.md +++ b/README.md @@ -48,12 +48,12 @@ You can define your own units. We can get frames per second by defining frames. ```python from quantity.unit import Unit -from quantity.quantity.quantity import Quantity +from quantity.quantity import Quantity frame = Unit('f', "frame") frames = Quantity(432000, "frame") -runningTime = Quantity(120 * 60, 's') -fps = frames / runningTime +running_time = Quantity(120 * 60, 's') +fps = frames / running_time print(fps) '60.0 f/s' ``` diff --git a/quantity/PyQuantity.egg-info/PKG-INFO b/quantity/PyQuantity.egg-info/PKG-INFO new file mode 100644 index 0000000..4c84412 --- /dev/null +++ b/quantity/PyQuantity.egg-info/PKG-INFO @@ -0,0 +1,13 @@ +Metadata-Version: 2.1 +Name: PyQuantity +Version: 1.1 +Summary: Quantities in Python +Home-page: UNKNOWN +Author: akm +Author-email: akm@unyx.net +License: BSD +Platform: UNKNOWN +License-File: LICENSE + +UNKNOWN + diff --git a/quantity/PyQuantity.egg-info/SOURCES.txt b/quantity/PyQuantity.egg-info/SOURCES.txt new file mode 100644 index 0000000..597c9d4 --- /dev/null +++ b/quantity/PyQuantity.egg-info/SOURCES.txt @@ -0,0 +1,14 @@ +LICENSE +README.md +setup.py +quantity/__init__.py +quantity/PyQuantity.egg-info/PKG-INFO +quantity/PyQuantity.egg-info/SOURCES.txt +quantity/PyQuantity.egg-info/dependency_links.txt +quantity/PyQuantity.egg-info/top_level.txt +quantity/quantity/__init__.py +quantity/quantity/quantity.py +test/test_prefix.py +test/test_quantity.py +test/test_quantity_config_parser.py +test/test_unit.py \ No newline at end of file diff --git a/quantity/PyQuantity.egg-info/dependency_links.txt b/quantity/PyQuantity.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/quantity/PyQuantity.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/quantity/PyQuantity.egg-info/top_level.txt b/quantity/PyQuantity.egg-info/top_level.txt new file mode 100644 index 0000000..1465ec5 --- /dev/null +++ b/quantity/PyQuantity.egg-info/top_level.txt @@ -0,0 +1,2 @@ + +quantity diff --git a/quantity/bit_field/bit_field.py b/quantity/bit_field/bit_field.py index a139d56..6a712d2 100644 --- a/quantity/bit_field/bit_field.py +++ b/quantity/bit_field/bit_field.py @@ -1,24 +1,24 @@ # -*- coding: utf-8 -*- +from typing import Union """ Numbers as BitField, this class is useful on its own, it is very useful as a superclass. >>> class MyField(BitField): >>> @property ->>> def subField(self): +>>> def sub_field(self): >>> return self[2:5] ->>> @subField.setter ->>> def subField(self, value): +>>> @sub_field.setter +>>> def sub_field(self, value): >>> self[2:5] = value >>> x = MyField(0x14) ->>> x.subField +>>> x.sub_field 5 ->>> x.subField = 7 ->>> x.subField +>>> x.sub_field = 7 +>>> x.sub_field 7 >>> hex(int(x)) 0x1c """ -__author__ = "akm" class BitField: @@ -39,7 +39,7 @@ class BitField: def __init__(self, value: int = 0): self.__value = value - def __getitem__(self, index: int) -> int: + def __getitem__(self, index: Union[int, slice]) -> int: """ Get a single bit, 0 indexed @@ -49,7 +49,7 @@ def __getitem__(self, index: int) -> int: return self.__getslice__(index) return (self.__value >> index) & 1 - def __setitem__(self, index: int, value: int): + def __setitem__(self, index: Union[int, slice], value: int): """ Set a single bit, 0 indexed diff --git a/quantity/prefix/__init__.py b/quantity/prefix/__init__.py index b24ffa3..eb95784 100644 --- a/quantity/prefix/__init__.py +++ b/quantity/prefix/__init__.py @@ -1,4 +1,3 @@ # -*- coding: utf-8 -*- -__author__ = 'akm' from .prefix import Prefix, has_power, has_prefix, get_power, get_prefix, closest_prefix from . import prefixes diff --git a/quantity/prefix/prefix.py b/quantity/prefix/prefix.py index 53b5226..61ec399 100644 --- a/quantity/prefix/prefix.py +++ b/quantity/prefix/prefix.py @@ -1,6 +1,4 @@ # -*- coding: utf-8 -*- -__author__ = 'akm' - from typing import Union """ @@ -94,8 +92,8 @@ def generate_format(self, power: int) -> str: elif power < 100: t, u = divmod(power, 10) return f'10{pPrefix}{self.supers[t]}{self.supers[u]}' - else: - return f'10^{pPrefix}{power}' + + return f'10^{pPrefix}{power}' def __repr__(self) -> str: """ @@ -104,9 +102,6 @@ def __repr__(self) -> str: return self.fmt def __str__(self) -> str: - """ - Ascii version - """ return f'{self.prefix}' def __rmul__(self, o) -> Union[int, float]: diff --git a/quantity/prefix/prefixes.py b/quantity/prefix/prefixes.py index 6b2b066..329de68 100644 --- a/quantity/prefix/prefixes.py +++ b/quantity/prefix/prefixes.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -__author__ = 'akm' from .prefix import Prefix # A flag to remove some of the prefixes we don't like to use diff --git a/quantity/quantity/quantity.py b/quantity/quantity/quantity.py index 48c1aa5..1803fb7 100644 --- a/quantity/quantity/quantity.py +++ b/quantity/quantity/quantity.py @@ -1,13 +1,9 @@ # -*- coding: utf-8 -*- -__author__ = "akm" from typing import Union, Optional -from quantity.unit.unit import Unit, get_unit, has_unit -from quantity.prefix.prefix import closest_prefix, has_prefix, get_prefix, Prefix +from quantity.unit import Unit, get_unit, has_unit, NoUnit +from quantity.prefix import closest_prefix, has_prefix, get_prefix, Prefix import quantity.prefix.prefixes as prefixes -import quantity.unit.units as units - -NO_UNIT = units.NoUnit class Quantity: @@ -45,7 +41,7 @@ class Quantity: :param prefix: A SI power prefix to be applied to the amount. """ - def __init__(self, amount, unit: Union[Unit, str] = NO_UNIT, prefix: Prefix = prefixes.NoPrefix): + def __init__(self, amount, unit: Union[Unit, str] = NoUnit, prefix: Prefix = prefixes.NoPrefix): self.amount = amount self.unit = unit self.prefix = prefix @@ -61,7 +57,7 @@ def __add__(self, o) -> 'Quantity': if isinstance(o, (int, float)) and o == 0: return self - if self.unit is NO_UNIT and isinstance(o, (int, float)): + if self.unit is NoUnit and isinstance(o, (int, float)): return Quantity(type(o)(self) + o) unit = self.unit + o.unit @@ -70,7 +66,7 @@ def __add__(self, o) -> 'Quantity': __radd__ = __add__ def __sub__(self, o) -> 'Quantity': - if self.unit is NO_UNIT and isinstance(o, (int, float)): + if self.unit is NoUnit and isinstance(o, (int, float)): return Quantity(type(o)(self) - o) unit = self.unit - o.unit @@ -107,7 +103,7 @@ def _strip_unit(self): """ Remove our unit type """ - self.unit = NO_UNIT + self.unit = NoUnit def __find_unit(self): """ @@ -117,7 +113,7 @@ def __find_unit(self): :return: :mod:`Unit` object """ if not self.unit: - return NO_UNIT + return NoUnit if isinstance(self.unit, Unit): return self.unit @@ -163,7 +159,7 @@ def __eq__(self, other) -> bool: Otherwise everything else has to match """ - if self.unit is NO_UNIT and isinstance(other, (int, float, int)): + if self.unit is NoUnit and isinstance(other, (int, float, int)): return type(other)(self) == other return (other.amount == self.amount and @@ -174,28 +170,28 @@ def __ne__(self, other) -> bool: return not (other == self) def __lt__(self, other) -> bool: - if self.unit is NO_UNIT and isinstance(other, (int, float, int)): + if self.unit is NoUnit and isinstance(other, (int, float, int)): return type(other)(self) > other assert other.unit is self.unit and other.prefix is self.prefix return self.amount < other.amount def __le__(self, other) -> bool: - if self.unit is NO_UNIT and isinstance(other, (int, float, int)): + if self.unit is NoUnit and isinstance(other, (int, float, int)): return type(other)(self) <= other assert other.unit is self.unit and other.prefix is self.prefix return self.amount <= other.amount def __gt__(self, other) -> bool: - if self.unit is NO_UNIT and isinstance(other, (int, float, int)): + if self.unit is NoUnit and isinstance(other, (int, float, int)): return type(other)(self) > other assert other.unit is self.unit and other.prefix is self.prefix return self.amount > other.amount def __ge__(self, other) -> bool: - if self.unit is NO_UNIT and isinstance(other, (int, float, int)): + if self.unit is NoUnit and isinstance(other, (int, float, int)): return type(other)(self) >= other assert other.unit is self.unit and other.prefix is self.prefix diff --git a/quantity/quantity_config_parser/quantity_config_parser.py b/quantity/quantity_config_parser/quantity_config_parser.py index 28d3da8..d10b746 100644 --- a/quantity/quantity_config_parser/quantity_config_parser.py +++ b/quantity/quantity_config_parser/quantity_config_parser.py @@ -4,7 +4,7 @@ from typing import Union, Callable from quantity.quantity import Quantity -import quantity.unit.units as Units +from quantity.unit import NoUnit _hex = partial(int, base=16) @@ -14,34 +14,7 @@ class QuantityConfigParser(ConfigParser): A :mod:`SafeConfigParser` derivative that returns quantities """ - @staticmethod - def __quantify(converter: Callable, value: Union[float, int], unit: str) -> Quantity: - """ - Return a type cast quantity - - :param converter: A conversion callable (i.e. int, float) - :param value: The value (1, 1.0, 100) - :param unit: The SI quantifier ('s', 'km') - :returns: A :mod:`Quantity` object - """ - return Quantity(converter(value), unit) - - def _splitSectionItem(self, section: str, option: str) -> tuple: - """ - Split a config value into value and unit - :param section: Config section - :param option: Config option - :return: :mod:`tuple` of value and unit - """ - s = self.get(section, option) - try: - value, unit = (x.strip() for x in s.split(None, 1)) - except ValueError: - value = s - unit = Units.NoUnit - return value, unit - - def getAs(self, section: str, option: str, converter: Callable) -> Quantity: + def get_as(self, section: str, option: str, converter: Callable) -> Quantity: """ Convert a section to a coerced Quantity :param section: Config section @@ -49,10 +22,10 @@ def getAs(self, section: str, option: str, converter: Callable) -> Quantity: :param converter: callable that returns a numeric type from a string (e.g int, float ) :return: :mod:`Quantity` """ - value, unit = self._splitSectionItem(section, option) + value, unit = self._split_section_item(section, option) return self.__quantify(converter, value, unit) - def getint(self, section: str, option: str, converter=int) -> Quantity: + def getint(self, section: str, option: str, converter: Callable = int) -> Quantity: """ A convenience method which coerces the option in the specified section to an integer :mod:`Quantity` @@ -62,7 +35,7 @@ def getint(self, section: str, option: str, converter=int) -> Quantity: :param converter: a string to int callable :return: :mod:`Quantity` """ - return self.getAs(section, option, converter) + return self.get_as(section, option, converter) def gethex(self, section: str, option: str, converter: Callable = _hex) -> Quantity: """ @@ -75,7 +48,7 @@ def gethex(self, section: str, option: str, converter: Callable = _hex) -> Quant :param converter: a hex string to int callable :return: :mod:`Quantity` """ - return self.getAs(section, option, converter) + return self.get_as(section, option, converter) def getfloat(self, section: str, option: str, converter: Callable = float) -> Quantity: """ @@ -87,4 +60,31 @@ def getfloat(self, section: str, option: str, converter: Callable = float) -> Qu :param converter: a string to float callable :return: :mod:`Quantity` """ - return self.getAs(section, option, converter) + return self.get_as(section, option, converter) + + def _split_section_item(self, section: str, option: str) -> tuple: + """ + Split a config value into value and unit + :param section: Config section + :param option: Config option + :return: :mod:`tuple` of value and unit + """ + s = self.get(section, option) + try: + value, unit = (x.strip() for x in s.split(None, 1)) + except ValueError: + value = s + unit = NoUnit + return value, unit + + @staticmethod + def __quantify(converter: Callable, value: Union[float, int], unit: str) -> Quantity: + """ + Return a type cast quantity + + :param converter: A conversion callable (i.e. int, float) + :param value: The value (1, 1.0, 100) + :param unit: The SI quantifier ('s', 'km') + :returns: A :mod:`Quantity` object + """ + return Quantity(converter(value), unit) diff --git a/quantity/unit/__init__.py b/quantity/unit/__init__.py index e2f9b79..9e94ba9 100644 --- a/quantity/unit/__init__.py +++ b/quantity/unit/__init__.py @@ -1,3 +1,4 @@ __author__ = 'akm' -from .unit import Unit, has_combined_unit, has_conversion, has_divided_unit, has_unit, get_conversion, get_unit, get_units +from .unit import (Unit, has_combined_unit, has_conversion, has_divided_unit, has_unit, get_conversion, get_unit, + get_units, NoUnit) from . import units diff --git a/quantity/unit/unit.py b/quantity/unit/unit.py index 34d6079..c495267 100644 --- a/quantity/unit/unit.py +++ b/quantity/unit/unit.py @@ -7,9 +7,9 @@ class MetaUnit(type): - unitIndex = {} - combinedUnits = {} - dividedUnits = {} + unit_index = {} + combined_units = {} + divided_units = {} conversions = {} def __call__(cls, *args, **kwargs): @@ -18,8 +18,8 @@ def __call__(cls, *args, **kwargs): """ obj = super(MetaUnit, cls).__call__(*args, **kwargs) if not ('temp' in kwargs and kwargs.get('temp')) or (len(args) == 3 and not args[-1]): - MetaUnit.unitIndex[obj.unit] = obj - MetaUnit.unitIndex[obj.name] = obj + MetaUnit.unit_index[obj.unit] = obj + MetaUnit.unit_index[obj.name] = obj return obj @@ -32,12 +32,12 @@ class Unit(metaclass=MetaUnit): :param temp: Is this a temporary unit (created when combining units) """ - xNames = ('', '', 'square ', 'cubic ', 'quartic') + x_names = ('', '', 'square ', 'cubic ', 'quartic', 'quintic', 'sextic', 'septic', 'octic', 'nonic', 'decic') # Unicode superscripts for powers , 0, 1, 2, 3, 4, 5 etc.. supers = ('⁰', '¹', '²', '³', '⁴', '⁵', '⁶', '⁷', '⁸', '⁹') - __slots__ = ('unit', 'name', '_unit', 'index', 'xName') + __slots__ = ('unit', 'name', '_unit', 'index', 'x_name') # temp is parsed by the meta class... def __init__(self, unit: str, name: str, temp: bool = False): @@ -45,7 +45,7 @@ def __init__(self, unit: str, name: str, temp: bool = False): self._unit = unit self.name = name self.index = 1 - self.xName = '' + self.x_name = '' def __add__(self, o): assert o is self @@ -144,13 +144,13 @@ def _updateName(self): """ Our unit changed to have an exponent, update our representation """ - if 1 <= self.index <= 4: - self.xName = self.xNames[self.index] + if 1 <= self.index <= len(self.x_names): + self.x_name = self.x_names[self.index] else: - self.xName = f'{self.index}th ' + self.x_name = f'{self.index}th ' def __repr__(self) -> str: - return f'{self.xName}{self.name}' + return f'{self.x_name}{self.name}' def __str__(self) -> str: return self.unit @@ -182,7 +182,7 @@ def get_units() -> tuple: Get all the units :return: """ - return tuple(MetaUnit.unitIndex.keys()) + return tuple(MetaUnit.unit_index.keys()) def get_all_conversions() -> dict: @@ -190,19 +190,19 @@ def get_all_conversions() -> dict: def get_all_divided_units() -> dict: - return MetaUnit.dividedUnits + return MetaUnit.divided_units def get_all_combined_units() -> dict: - return MetaUnit.combinedUnits + return MetaUnit.combined_units def get_unit(unitName) -> Unit: - return MetaUnit.unitIndex[unitName] + return MetaUnit.unit_index[unitName] def get_combined_unit(unit) -> Unit: - return MetaUnit.combinedUnits[unit] + return MetaUnit.combined_units[unit] def get_conversion(units): @@ -210,15 +210,15 @@ def get_conversion(units): def get_divided_unit(unit) -> Unit: - return MetaUnit.dividedUnits[unit] + return MetaUnit.divided_units[unit] def has_unit(unit_id: str) -> bool: - return unit_id in MetaUnit.unitIndex + return unit_id in MetaUnit.unit_index def has_combined_unit(unit_id) -> bool: - return unit_id in MetaUnit.combinedUnits + return unit_id in MetaUnit.combined_units def has_conversion(units) -> bool: @@ -226,4 +226,4 @@ def has_conversion(units) -> bool: def has_divided_unit(units) -> bool: - return units in MetaUnit.dividedUnits + return units in MetaUnit.divided_units diff --git a/quantity/unit/units.py b/quantity/unit/units.py index a614af0..4f3a78d 100644 --- a/quantity/unit/units.py +++ b/quantity/unit/units.py @@ -22,11 +22,9 @@ Ohm * Ampere * Ampere -> Volt * Ampere -> Watt Ampere * (Ampere * Ohm) -> Ampere * Volt -> Watt """ -__author__ = 'akm' - import operator -from .unit import NoUnit, Unit, get_all_conversions, get_all_divided_units, get_all_combined_units +from .unit import Unit, get_all_conversions, get_all_divided_units, get_all_combined_units # SI Base units metre = Unit('m', "metre") # : SI metre diff --git a/setup.py b/setup.py index b7f4c7c..4b5d3c8 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup( name='PyQuantity', - version='1.0', + version='1.1', packages=['', 'quantity'], package_dir={'': 'quantity'}, url='', diff --git a/test/TestData/Test.ini b/tests/TestData/test.ini similarity index 100% rename from test/TestData/Test.ini rename to tests/TestData/test.ini diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/test_prefix.py b/tests/test_prefix.py similarity index 100% rename from test/test_prefix.py rename to tests/test_prefix.py diff --git a/test/test_quantity.py b/tests/test_quantity.py similarity index 100% rename from test/test_quantity.py rename to tests/test_quantity.py diff --git a/test/test_quantity_config_parser.py b/tests/test_quantity_config_parser.py similarity index 100% rename from test/test_quantity_config_parser.py rename to tests/test_quantity_config_parser.py diff --git a/test/test_unit.py b/tests/test_unit.py similarity index 74% rename from test/test_unit.py rename to tests/test_unit.py index 2ad1f5a..71d2681 100644 --- a/test/test_unit.py +++ b/tests/test_unit.py @@ -2,6 +2,7 @@ import unittest from quantity.unit import Unit, has_unit +from quantity.unit import NoUnit import quantity.unit.units as units @@ -16,16 +17,16 @@ def testSimpleUnit(self): def testAddition(self): assert units.volt + units.volt is units.volt self.assertRaises(AssertionError, units.volt.__add__, units.ohm) - self.assertRaises(AssertionError, units.volt.__add__, units.NoUnit) + self.assertRaises(AssertionError, units.volt.__add__, NoUnit) def testSubtraction(self): assert units.ampere - units.ampere is units.ampere self.assertRaises(AssertionError, units.ohm.__sub__, units.volt) - self.assertRaises(AssertionError, units.ohm.__sub__, units.NoUnit) + self.assertRaises(AssertionError, units.ohm.__sub__, NoUnit) def testDivision(self): - assert units.ampere / units.ampere is units.NoUnit - assert units.ampere / units.NoUnit is units.ampere + assert units.ampere / units.ampere is NoUnit + assert units.ampere / NoUnit is units.ampere def testCombinedDivision(self): # Do we collapse the units? @@ -36,14 +37,14 @@ def testCombinedDivision(self): assert not has_unit(x) def testMultiplication(self): - assert units.NoUnit * units.watt is units.watt - assert units.watt * units.NoUnit is units.watt - assert units.NoUnit * units.NoUnit is units.NoUnit + assert NoUnit * units.watt is units.watt + assert units.watt * NoUnit is units.watt + assert NoUnit * NoUnit is NoUnit w2 = units.watt * units.watt assert w2._unit is units.watt._unit assert w2.name is units.watt.name - assert w2.index is 2 + assert w2.index == 2 def testCombinedMultiplication(self): # Do we make the special units?