From adaf8b11b9eefc03bfac8051dec657a2257ab884 Mon Sep 17 00:00:00 2001 From: arofarn Date: Mon, 28 Jun 2021 13:50:17 +0200 Subject: [PATCH] Add package_tools module for exporter --- examples/umetpy_simpletest.py | 8 ++- umetpy/constants.py | 98 +++++++++++++++++++---------------- umetpy/package_tools.py | 63 ++++++++++++++++++++++ 3 files changed, 119 insertions(+), 50 deletions(-) create mode 100644 umetpy/package_tools.py diff --git a/examples/umetpy_simpletest.py b/examples/umetpy_simpletest.py index 6d08e55..1f81ba4 100644 --- a/examples/umetpy_simpletest.py +++ b/examples/umetpy_simpletest.py @@ -3,12 +3,10 @@ # # SPDX-License-Identifier: BSD-3-Clause -import umetpy.constants +import umetpy.constants as mpconsts # pylint: disable=eval-used print("List of all constants:\n") -for cst in dir(umetpy.constants): +for cst in dir(mpconsts): if cst[0] != "_": - print( - "{:25s} = {:f}".format(cst, eval("{}.{}".format("umetpy.constants", cst))) - ) + print("{:30s} = {:.12f}".format(cst, eval("{}.{}".format("mpconsts", cst)))) diff --git a/umetpy/constants.py b/umetpy/constants.py index 5ff2059..10774e5 100644 --- a/umetpy/constants.py +++ b/umetpy/constants.py @@ -4,7 +4,7 @@ # pylint: disable=line-too-long -r"""A collection of meteorologically significant constant and thermophysical property values. +r"""A collection of meteorologically significant constants and thermophysical property values. Earth ----- @@ -75,52 +75,60 @@ molecular_weight_ratio :math:`\epsilon` epsilon :math:`\text{None}` # pylint: enable=line-too-long # pylint: disable=invalid-name +from .package_tools import Exporter -# Earth -earth_gravity = g = 9.80665 # 'm / s^2' -Re = earth_avg_radius = 6371008.7714 # 'm' -G = gravitational_constant = 6.67430e-11 # 'm^3 / kg / s^2' -GM = geocentric_gravitational_constant = 3986005e8 # 'm^3 / s^2' -omega = earth_avg_angular_vel = 7292115e-11 # 'rad / s' -d = earth_sfc_avg_dist_sun = 149597870700.0 # 'm' -S = earth_solar_irradiance = 1360.8 # 'W / m^2' -delta = earth_max_declination = 23.45 # 'degrees' -earth_orbit_eccentricity = 0.0167 # 'dimensionless' -earth_mass = me = geocentric_gravitational_constant / gravitational_constant +exporter = Exporter(globals()) -# molar gas constant -R = 8.314462618 # 'J / mol / K' +# Export all the variables defined in this block +with exporter: + # Earth + earth_gravity = g = 9.80665 # 'm / s^2' + Re = earth_avg_radius = 6371008.7714 # 'm' + G = gravitational_constant = 6.67430e-11 # 'm^3 / kg / s^2' + GM = geocentric_gravitational_constant = 3986005e8 # 'm^3 / s^2' + omega = earth_avg_angular_vel = 7292115e-11 # 'rad / s' + d = earth_sfc_avg_dist_sun = 149597870700.0 # 'm' + S = earth_solar_irradiance = 1360.8 # 'W / m^2' + delta = earth_max_declination = 23.45 # 'degrees' + earth_orbit_eccentricity = 0.0167 # 'dimensionless' + earth_mass = me = geocentric_gravitational_constant / gravitational_constant -# Water -Mw = water_molecular_weight = 18.015268 # 'g / mol' -Rv = water_gas_constant = R / Mw -rho_l = density_water = 999.97495 # 'kg / m^3' -wv_specific_heat_ratio = 1.330 # 'dimensionless' -Cp_v = wv_specific_heat_press = ( - wv_specific_heat_ratio * Rv / (wv_specific_heat_ratio - 1) -) -Cv_v = wv_specific_heat_vol = Cp_v / wv_specific_heat_ratio -Cp_l = water_specific_heat = 4.2194 # 'kJ / kg / K' -Lv = water_heat_vaporization = 2.50084e6 # 'J / kg' -Lf = water_heat_fusion = 3.337e5 # 'J / kg' -Cp_i = ice_specific_heat = 2090 # 'J / kg / K' -rho_i = density_ice = 917 # 'kg / m^3' + # molar gas constant + R = 8.314462618 # 'J / mol / K' -# Dry air -Md = dry_air_molecular_weight = 28.96546e-3 # 'kg / mol' -Rd = dry_air_gas_constant = R / Md -dry_air_spec_heat_ratio = 1.4 # 'dimensionless' -Cp_d = dry_air_spec_heat_press = ( - dry_air_spec_heat_ratio * Rd / (dry_air_spec_heat_ratio - 1) -) -Cv_d = dry_air_spec_heat_vol = Cp_d / dry_air_spec_heat_ratio -# TODO : check unit conversion -# rho_d = dry_air_density_stp = (1000., 'mbar') / (Rd * 273.15, 'K'))) # 'kg / m^3' + # Water + Mw = water_molecular_weight = 18.015268 # 'g / mol' + Rv = water_gas_constant = R / Mw + rho_l = density_water = 999.97495 # 'kg / m^3' + wv_specific_heat_ratio = 1.330 # 'dimensionless' + Cp_v = wv_specific_heat_press = ( + wv_specific_heat_ratio * Rv / (wv_specific_heat_ratio - 1) + ) + Cv_v = wv_specific_heat_vol = Cp_v / wv_specific_heat_ratio + Cp_l = water_specific_heat = 4.2194 # 'kJ / kg / K' + Lv = water_heat_vaporization = 2.50084e6 # 'J / kg' + Lf = water_heat_fusion = 3.337e5 # 'J / kg' + Cp_i = ice_specific_heat = 2090 # 'J / kg / K' + rho_i = density_ice = 917 # 'kg / m^3' -# General meteorology constants -P0 = pot_temp_ref_press = 1000.0 # 'mbar' -# TODO : check unit conversion -kappa = poisson_exponent = Rd / Cp_d # 'dimensionless' -gamma_d = dry_adiabatic_lapse_rate = g / Cp_d -# TODO : check unit conversion -epsilon = molecular_weight_ratio = Mw / Md # 'dimensionless' + # Dry air + Md = dry_air_molecular_weight = 28.96546e-3 # 'kg / mol' + Rd = dry_air_gas_constant = R / Md + dry_air_spec_heat_ratio = 1.4 # 'dimensionless' + Cp_d = dry_air_spec_heat_press = ( + dry_air_spec_heat_ratio * Rd / (dry_air_spec_heat_ratio - 1) + ) + Cv_d = dry_air_spec_heat_vol = Cp_d / dry_air_spec_heat_ratio + # TODO : check unit conversion + rho_d = dry_air_density_stp = 1000.0 / (Rd * 273.15) # 'kg / m^3' + + # General meteorology constants + P0 = pot_temp_ref_press = 1000.0 # 'mbar' + # TODO : check unit conversion + kappa = poisson_exponent = Rd / Cp_d # 'dimensionless' + gamma_d = dry_adiabatic_lapse_rate = g / Cp_d + # TODO : check unit conversion + epsilon = molecular_weight_ratio = Mw / Md # 'dimensionless' + +del exporter +del Exporter diff --git a/umetpy/package_tools.py b/umetpy/package_tools.py new file mode 100644 index 0000000..a523ca7 --- /dev/null +++ b/umetpy/package_tools.py @@ -0,0 +1,63 @@ +# Copyright (c) 2015,2018,2019 MetPy Developers. +# Distributed under the terms of the BSD 3-Clause License. +# SPDX-License-Identifier: BSD-3-Clause +"""Collection of tools for managing the package.""" + +# Used to specify functions that should be exported--i.e. added to __all__ +# Inspired by David Beazley and taken from python-ideas: +# https://mail.python.org/pipermail/python-ideas/2014-May/027824.html + +__all__ = ("Exporter",) + + +class Exporter: + """Manages exporting of symbols from the module. + + Grabs a reference to `globals()` for a module and provides a decorator to add + functions and classes to `__all__` rather than requiring a separately maintained list. + Also provides a context manager to do this for instances by adding all instances added + within a block to `__all__`. + """ + + def __init__(self, globls): + """Initialize the Exporter.""" + self.globls = globls + self.exports = globls.setdefault("__all__", []) + + def export(self, defn): + """Declare a function or class as exported.""" + self.exports.append(defn.__name__) + return defn + + def __enter__(self): + """Start a block tracking all instances created at global scope.""" + # pylint: disable=attribute-defined-outside-init + self.start_vars = set(self.globls) + # pylint: enable=attribute-defined-outside-init + + def __exit__(self, exc_type, exc_val, exc_tb): + """Exit the instance tracking block.""" + self.exports.extend(set(self.globls) - self.start_vars) + del self.start_vars + + +def set_module(globls): + """Set the module for all functions in ``__all__``. + + This sets the ``__module__`` attribute of all items within the ``__all__`` list + for the calling module. + + This supports our hoisting of functions out of individual modules, which are + considered implementation details, into the namespace of the top-level subpackage. + + Parameters + ---------- + globls : Dict[str, object] + Mapping of all global variables for the module. This contains all needed + python special ("dunder") variables needed to be modified. + + """ + for item in globls["__all__"]: + obj = globls[item] + if hasattr(obj, "__module__"): + obj.__module__ = globls["__name__"]