Coverage for pygeodesy/basics.py : 97%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# -*- coding: utf-8 -*-
''' # make sure int/int division yields float quotient raise ImportError('%s 1/2 == %s' % ('division', division))
_TypesError, _ValueError, _xError, _xkwds_get _by_, _DOT_, _INF_, _invalid_, _N_A_, _name_, \ _NAN_, _SPACE_, _UNDER_, _utf_8_, _version_, \ _0_0, _0_5, _1_0, _360_0
except ImportError: try: _Ints = int, long # int objects (C{tuple}) except NameError: # Python 3+ _Ints = int, # int objects (C{tuple}) _Scalars = _Ints + (float,)
except ImportError: # no .abc in Python 3.8- and 2.7- from collections import Sequence as _Sequence # in .points # and isinstance(range(1), _Sequence): else: raise ImportError # _AssertionError except ImportError: _Sequence = tuple # immutable for .points._Basequence _Seqs = list, _Sequence # , range for function len2 below
_Strs = basestring, str # XXX , bytes
def _Xstr(exc): # PYCHOK no cover '''I{Invoke only with caught ImportError} B{C{exc}}.
C{... "cannot import name _distributor_init" ...}
only for C{numpy}, C{scipy} import errors occurring on arm64 Apple Silicon running macOS' Python 2.7.16? ''' t = str(exc) if '_distributor_init' in t: from sys import exc_info from traceback import extract_tb tb = exc_info()[2] # 3-tuple (type, value, traceback) t4 = extract_tb(tb, 1)[0] # 4-tuple (file, line, name, 'import ...') t = _SPACE_('cannot', t4[3] or _N_A_) del tb, t4 return t
except NameError: # Python 3+ _Bytes = bytes, bytearray _Strs = str, # tuple _Xstr = str
'''Clip a string to the given length limit.
@arg bstr: String (C{bytes} or C{str}). @kwarg limit: Length limit (C{int}). @kwarg white: Optionally, replace all whitespace (C{str}).
@return: The clipped or unclipped B{C{bstr}}. '''
'''Like C{math.copysign(x, y)} except C{zero}, I{unsigned}.
@return: C{math.copysign(B{x}, B{y})} if B{C{x}} else C{type(B{x})(0)}. '''
'''Return the value of B{x} as C{type} of C{y}.
@return: C{type(B{y})(B{x})}. '''
'''Split a string in 2 halfs.
@arg str2: String to split (C{str}).
@return: 2-Tuple (_1st, _2nd) half (C{str}).
@raise ValueError: Zero or odd C{len}(B{C{str2}}). ''' raise _ValueError(str2=str2, txt=_odd_)
'''Check whether an object is C{bool}ean.
@arg obj: The object (any C{type}).
@return: C{True} if B{C{obj}} is C{bool}ean, C{False} otherwise. ''' # or obj is False)
if _FOR_DOCS: # XXX avoid epidoc Python 2.7 error from inspect import isclass as _isclass
def isclass(obj): '''Return C{True} if B{C{obj}} is a C{class}.
@see: Python's C{inspect.isclass}. ''' return _isclass(obj) else:
'''Check whether an object is C{complex}.
@arg obj: The object (any C{type}).
@return: C{True} if B{C{obj}} is C{complex}, C{False} otherwise. '''
'''Check for non-finite C{scalar} value.
@arg obj: Value (C{scalar}).
@return: C{False} if B{C{obj}} is C{INF}, C{NINF} or C{NAN}, C{True} otherwise.
@raise TypeError: Non-scalar B{C{obj}}. ''' except Exception as x: P = _MODS.streprs.Fmt.PAREN raise _xError(x, P(isfinite.__name__, obj))
except ImportError: # Python 3.1-
def _isfinite(x): '''Mimick Python 3.2+ C{math.isfinite}. ''' return not (isinf(x) or isnan(x))
except AttributeError: # Python 2-
def isidentifier(obj): '''Return C{True} if B{C{obj}} is a valid Python identifier. ''' return bool(obj and obj.replace(_UNDER_, NN).isalnum() and not obj[:1].isdigit())
# from math import isinf
'''Check for C{int} type or an integer C{float} value.
@arg obj: The object (any C{type}). @kwarg both: If C{true}, check C{float} and L{Fsum} type and value (C{bool}).
@return: C{True} if B{C{obj}} is C{int} or an integer C{float} or L{Fsum}, C{False} otherwise.
@note: C{isint(True)} or C{isint(False)} returns C{False} (and no longer C{True}). ''' except AttributeError: pass # XXX float(int(obj)) == obj?
'''Check for L{INT0} or C{int(0)} value.
@arg obj: The object (any C{type}). @kwarg both: If C{true}, also check C{float(0)} (C{bool}).
@return: C{True} if B{C{obj}} is L{INT0}, C{int(0)} or C{float(0)}, C{False} otherwise. ''' (not obj) and isint(obj, both=True))) and not isbool(obj)
except ImportError:
def iskeyword(unused): '''Not Implemented. Return C{False}, always. ''' return False
# from math import isnan
'''Is B{C{x}} near zero?
@arg x: Value (C{scalar}). @kwarg eps0: Near-zero (C{EPS0}).
@return: C{True} if C{abs(B{x}) < B{eps0}}, C{False} otherwise.
@see: Function L{isnon0}. '''
'''Is B{C{x}} near one?
@arg x: Value (C{scalar}). @kwarg eps0: Near-zero (C{EPS0}).
@return: C{isnear0(B{x} - 1)}.
@see: Function L{isnear0}. '''
'''Check for L{NEG0}, negative C{0.0}.
@arg x: Value (C{scalar}).
@return: C{True} if B{C{x}} is C{NEG0} or C{-0.0}, C{False} otherwise. ''' # and str(x).startswith(_MINUS_)
'''Check for L{NINF}, negative C{INF}.
@arg x: Value (C{scalar}).
@return: C{True} if B{C{x}} is C{NINF} or C{-inf}, C{False} otherwise. '''
'''Is B{C{x}} non-zero?
@arg x: Value (C{scalar}). @kwarg eps0: Near-zero (C{EPS0}).
@return: C{True} if C{abs(B{x}) > B{eps0}}, C{False} otherwise.
@see: Function L{isnear0}. '''
'''Is B{C{x}} odd?
@arg x: Value (C{scalar}).
@return: C{True} if B{C{x}} is odd, C{False} otherwise. '''
'''Check for scalar types.
@arg obj: The object (any C{type}).
@return: C{True} if B{C{obj}} is C{scalar}, C{False} otherwise. '''
'''Check for sequence types.
@arg obj: The object (any C{type}). @arg excls: Classes to exclude (C{type}), all positional.
@note: Excluding C{tuple} implies excluding C{namedtuple}.
@return: C{True} if B{C{obj}} is a sequence, C{False} otherwise. '''
'''Check for string types.
@arg obj: The object (any C{type}).
@return: C{True} if B{C{obj}} is C{str}, C{False} otherwise. '''
'''Check whether a class is a sub-class of some other class(es).
@arg Sub: The sub-class (C{class}). @arg Supers: One or more C(super) classes (C{class}).
@return: C{True} if B{C{Sub}} is a sub-class of any B{C{Supers}}, C{False} if not (C{bool}) or C{None} if B{C{Sub}} is not a class or if no B{C{Supers}} are given or none of those are a class. '''
'''Make built-in function L{len} work for generators, iterators, etc. since those can only be started exactly once.
@arg items: Generator, iterator, list, range, tuple, etc.
@return: 2-Tuple C{(n, items)} of the number of items (C{int}) and the items (C{list} or C{tuple}). '''
'''Apply each argument to a single-argument function and return a C{tuple} of results.
@arg fun1: 1-Arg function to apply (C{callable}). @arg xs: Arguments to apply (C{any positional}).
@return: Function results (C{tuple}). '''
'''Apply arguments to a function and return a C{tuple} of results.
Unlike Python 2's built-in L{map}, Python 3+ L{map} returns a L{map} object, an iterator-like object which generates the results only once. Converting the L{map} object to a tuple maintains the Python 2 behavior.
@arg func: Function to apply (C{callable}). @arg xs: Arguments to apply (C{list, tuple, ...}).
@return: Function results (C{tuple}). '''
'''Negate C{x} unless C{zero} or C{NEG0}.
@return: C{-B{x}} if B{C{x}} else C{0.0}. '''
'''Negate all of C{xs} with L{neg}.
@return: A C{tuple(neg(x) for x in B{xs})}. '''
except ImportError: # Python 3.6- from math import fmod as _fmod
def remainder(x, y): '''Mimick Python 3.7+ C{math.remainder}. ''' if isnan(y): x = NAN elif x and not isnan(x): y = abs(y) x = _fmod(x, y) h = _0_5 * y if x < -h: x += y elif x >= h: x -= y return x # keep signed 0.0
'''(INTERNAL) Return the sign of B{C{x}} versus B{C{off}}. '''
'''Return sign of C{x} as C{int}.
@return: -1, 0 or +1 (C{int}). ''' except AttributeError: s = _signOf(x, 0)
'''Split an iterable into C{n} slices.
@arg iterable: Items to be spliced (C{list}, C{tuple}, ...). @kwarg n: Number of slices to generate (C{int}). @kwarg fill: Optional fill value for missing items.
@return: A generator for each of B{C{n}} slices, M{iterable[i::n] for i=0..n}.
@raise TypeError: Invalid B{C{n}}.
@note: Each generated slice is a C{tuple} or a C{list}, the latter only if the B{C{iterable}} is a C{list}.
@example:
>>> from pygeodesy import splice
>>> a, b = splice(range(10)) >>> a, b ((0, 2, 4, 6, 8), (1, 3, 5, 7, 9))
>>> a, b, c = splice(range(10), n=3) >>> a, b, c ((0, 3, 6, 9), (1, 4, 7), (2, 5, 8))
>>> a, b, c = splice(range(10), n=3, fill=-1) >>> a, b, c ((0, 3, 6, 9), (1, 4, 7, -1), (2, 5, 8, -1))
>>> tuple(splice(list(range(9)), n=5)) ([0, 5], [1, 6], [2, 7], [3, 8], [4])
>>> splice(range(9), n=1) <generator object splice at 0x0...> ''' raise _TypeError(n=n)
# XXX t[i::n] chokes PyChecker else: yield t
'''Convert C{unicode} or C{bytes} to C{str}. '''
'''(INTERNAL) Non-negative C{deg} modulo 360, basic C{.utily.wrap360}. '''
'''Return C{0.0} unsigned.
@return: C{B{x}} if B{C{x}} else C{0.0}. '''
'''(INTERNAL) Copy an object, shallow or deep.
@arg inst: The object to copy (any C{type}). @kwarg deep: If C{True} make a deep, otherwise a shallow copy (C{bool}).
@return: The copy of B{C{inst}}. '''
'''(INTERNAL) Duplicate an object, replacing some attributes.
@arg inst: The object to copy (any C{type}). @kwarg items: Attributes to be changed (C{any}).
@return: Shallow duplicate of B{C{inst}} with modified attributes, if any B{C{items}}.
@raise AttributeError: Some B{C{items}} invalid. ''' from pygeodesy.named import classname t = _SPACE_(_DOT_(classname(inst), n), _invalid_) raise _AttributeError(txt=t, this=inst, **items)
'''(INTERNAL) Import C{geographiclib} and check required version ''' except ImportError as x: raise _xImportError(x, where)
'''(INTERNAL) Embellish an C{ImportError}. '''
'''(INTERNAL) Check C{Types} of all C{name=value} pairs.
@arg Types: One or more classes or types (C{class}), all positional. @kwarg name_value_pairs: One or more C{B{name}=value} pairs with the C{value} to be checked.
@raise TypeError: One of the B{C{name_value_pairs}} is not an instance of any of the B{C{Types}}. ''' raise _TypesError(n, v, *Types)
'''(INTERNAL) Import C{numpy} and check required version ''' except ImportError as x: raise _xImportError(x, where)
'''(INTERNAL) Exclusive-or C{x} and C{xs}. '''
'''(INTERNAL) Import C{scipy} and check required version ''' except ImportError as x: raise _xImportError(x, where)
'''(INTERNAL) Check (super) class of all C{name=value} pairs.
@arg Classes: One or more classes or types (C{class}), all positional. @kwarg name_value_pairs: One or more C{B{name}=value} pairs with the C{value} to be checked.
@raise TypeError: One of the B{C{name_value_pairs}} is not a (sub-)class of any of the B{C{Classes}}. ''' raise _TypesError(n, v, *Classes)
'''(INTERNAL) Check the C{package} version vs B{C{required}}. ''' except AttributeError: t = package.__version__.strip() t = t.replace(_DOT_, _SPACE_).split()[:3] t = _SPACE_(package.__name__, _version_, _DOT_(*t), _below_, _DOT_(*required), _required_, _by_, _xwhere(where, **name)) raise ImportError(t)
'''(INTERNAL) Get the fully qualified name. ''' m = _DOT_(m, n)
# **) MIT License # # Copyright (C) 2016-2022 -- mrJean1 at Gmail -- All Rights Reserved. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. |