From a7e11f851fcb14d558abb59504774c6529e8047f Mon Sep 17 00:00:00 2001 From: Alexandre Detiste Date: Wed, 27 Nov 2024 22:27:07 +0100 Subject: [PATCH] replace custom @require_keywords decorator with modern syntax --- periodictable/formulas.py | 8 ++--- periodictable/nsf.py | 11 +++--- periodictable/util.py | 71 --------------------------------------- periodictable/xsf.py | 16 +++------ 4 files changed, 12 insertions(+), 94 deletions(-) diff --git a/periodictable/formulas.py b/periodictable/formulas.py index 31ad42e..5940f2b 100644 --- a/periodictable/formulas.py +++ b/periodictable/formulas.py @@ -14,7 +14,7 @@ from .core import default_table, isatom, isisotope, ision, change_table from .constants import avogadro_number -from .util import require_keywords, cell_volume +from .util import cell_volume PACKING_FACTORS = dict(cubic=pi/6, bcc=pi*sqrt(3)/8, hcp=pi/sqrt(18), fcc=pi/sqrt(18), diamond=pi*sqrt(3)/16) @@ -518,8 +518,7 @@ def volume(self, *args, **kw): packing_factor = PACKING_FACTORS[packing_factor.lower()] return V/packing_factor*1e-24 - @require_keywords - def neutron_sld(self, wavelength=None, energy=None): + def neutron_sld(self, *, wavelength=None, energy=None): """ Neutron scattering information for the molecule. @@ -543,8 +542,7 @@ def neutron_sld(self, wavelength=None, energy=None): return neutron_sld(self.atoms, density=self.density, wavelength=wavelength, energy=energy) - @require_keywords - def xray_sld(self, energy=None, wavelength=None): + def xray_sld(self, *, energy=None, wavelength=None): """ X-ray scattering length density for the molecule. diff --git a/periodictable/nsf.py b/periodictable/nsf.py index 87f404e..63abfe1 100644 --- a/periodictable/nsf.py +++ b/periodictable/nsf.py @@ -188,7 +188,7 @@ from .core import Element, Isotope, default_table from .constants import (avogadro_number, planck_constant, electron_volt, neutron_mass, atomic_mass_constant) -from .util import require_keywords, parse_uncertainty +from .util import parse_uncertainty __all__ = ['init', 'Neutron', 'neutron_energy', 'neutron_wavelength', @@ -483,8 +483,7 @@ def scattering_by_wavelength(self, wavelength): sigma_s = _4PI_100*abs(b_c)**2 # 1 barn = 1 fm^2 1e-2 barn/fm^2 return b_c, sigma_s - @require_keywords - def sld(self, wavelength=ABSORPTION_WAVELENGTH): + def sld(self, *, wavelength=ABSORPTION_WAVELENGTH): r""" Returns scattering length density for the element at natural abundance and density. @@ -505,8 +504,7 @@ def sld(self, wavelength=ABSORPTION_WAVELENGTH): return None, None, None return self.scattering(wavelength=wavelength)[0] - @require_keywords - def scattering(self, wavelength=ABSORPTION_WAVELENGTH): + def scattering(self, *, wavelength=ABSORPTION_WAVELENGTH): r""" Returns neutron scattering information for the element at natural abundance and density. @@ -650,8 +648,7 @@ def init(table, reload=False): # TODO: split incoherent into spin and isotope incoherence (eq 17-19 of Sears) # TODO: require parsed compound rather than including formula() keywords in api # Note: docs and function prototype are reproduced in __init__ -@require_keywords -def neutron_scattering(compound, density=None, +def neutron_scattering(compound, *, density=None, wavelength=None, energy=None, natural_density=None, table=None): r""" diff --git a/periodictable/util.py b/periodictable/util.py index 2f9c25e..e729547 100644 --- a/periodictable/util.py +++ b/periodictable/util.py @@ -91,74 +91,3 @@ def cell_volume(a=None, b=None, c=None, alpha=None, beta=None, gamma=None): cgamma = cos(radians(gamma)) if gamma is not None else calpha V = a*b*c*sqrt(1 - calpha**2 - cbeta**2 - cgamma**2 + 2*calpha*cbeta*cgamma) return V - -def require_keywords(function): - r""" - Decorator which forces all keyword arguments to the function to be - explicitly named. - - For example: - - >>> @require_keywords - ... def fn(a, b, c=3): pass - >>> fn(1, 2, 3) - Traceback (most recent call last): - ... - TypeError: name=value required for c - >>> fn(1, 2, c=6) - >>> fn(b=1, a=2, c=6) - - Variable arguments are not currently supported: - - >>> @require_keywords - ... def fn(a, b, c=6, *args, **kw): pass - Traceback (most recent call last): - ... - NotImplementedError: only named arguments for now - - .. Note:: The call signature is not preserved. - - We can't preserve the function signature for the call since the only - way we can count the number of non-keyword arguments is to - use the \*args, \*\*kw call style. Python 3+ provides the '\*' call - signature element which will force all keywords after '\*' to be named. - """ - import functools - try: - from inspect import signature - getargspec = _getargspec_from_signature - except ImportError: # CRUFT: py 2.7 support - from inspect import getargspec - - args, vararg, varkwd, defaults = getargspec(function) - if defaults is None: - defaults = [] - named_args = args[:-len(defaults)] - named_kwds = args[-len(defaults):] - # Keep it simple for now - if vararg or varkwd: - raise NotImplementedError("only named arguments for now") - @functools.wraps(function) - def _require_kwds(*args, **kw): - if len(args) > len(named_args): - raise TypeError("name=value required for "+", ".join(named_kwds)) - return function(*args, **kw) - return _require_kwds - -def _getargspec_from_signature(function): - """ - Reproduce getargspec() interface using newer signature protocol - """ - from inspect import signature - - args, vararg, varkwd, defaults = [], None, None, [] - sig = signature(function) - for p in sig.parameters.values(): - args.append(p.name) - if p.default is not p.empty: - defaults.append(p.default) - if p.kind is p.VAR_POSITIONAL: - vararg = p.name - elif p.kind is p.VAR_KEYWORD: - varkwd = p.name - return args, vararg, varkwd, defaults diff --git a/periodictable/xsf.py b/periodictable/xsf.py index eae2591..a1a5950 100644 --- a/periodictable/xsf.py +++ b/periodictable/xsf.py @@ -193,7 +193,6 @@ from .constants import ( avogadro_number, planck_constant, speed_of_light, electron_volt, electron_radius) -from .util import require_keywords def xray_wavelength(energy): r""" @@ -271,8 +270,7 @@ def _gettable(self): return self._table sftable = property(_gettable, doc="X-ray scattering factor table (E,f1,f2)") - @require_keywords - def scattering_factors(self, energy=None, wavelength=None): + def scattering_factors(self, *, energy=None, wavelength=None): """ X-ray scattering factors f', f''. @@ -337,8 +335,7 @@ def f0(self, Q): charge=self.element.charge) return f - @require_keywords - def sld(self, wavelength=None, energy=None): + def sld(self, *, wavelength=None, energy=None): r""" X ray scattering length density. @@ -382,8 +379,7 @@ def sld(self, wavelength=None, energy=None): return rho, irho # Note: docs and function prototype are reproduced in __init__ -@require_keywords -def xray_sld(compound, density=None, natural_density=None, +def xray_sld(compound, *, density=None, natural_density=None, wavelength=None, energy=None): """ Compute xray scattering length densities for molecules. @@ -435,8 +431,7 @@ def xray_sld(compound, density=None, natural_density=None, return rho, irho -@require_keywords -def index_of_refraction(compound, density=None, natural_density=None, +def index_of_refraction(compound, *, density=None, natural_density=None, energy=None, wavelength=None): """ Calculates the index of refraction for a given compound @@ -470,8 +465,7 @@ def index_of_refraction(compound, density=None, natural_density=None, wavelength=wavelength) return 1 - wavelength**2/(2*pi)*(f1 + f2*1j)*1e-6 -@require_keywords -def mirror_reflectivity(compound, density=None, natural_density=None, +def mirror_reflectivity(compound, *, density=None, natural_density=None, energy=None, wavelength=None, angle=None, roughness=0): """