Coverage for pygeodesy/errors.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 -*-
Error, exception classes and functions to format PyGeodesy errors, including the setting of I{exception chaining} in Python 3+.
By default, I{exception chaining} is turned off. To enable I{exception chaining}, use command line option C{python -X dev} or set environment variable C{PYTHONDEVMODE} to C{1} or any non-empyty string OR set environment variable C{PYGEODESY_EXCEPTION_CHAINING} to C{'std'} or any other non-empty string. ''' _COLON_, _COMMA_, _COMMASPACE_, \ _datum_, _ellipsoidal_, _EQUAL_, \ _invalid_, _len_, _name_, _no_, \ _not_, _or_, _SPACE_, _UNDER_, __vs__
_exception_chaining = True # turned on, std raise AttributeError # allow exception chaining
'''(INTERNAL) Set or avoid Python 3+ exception chaining.
Setting C{inst.__cause__ = None} is equivalent to syntax C{raise Error(...) from None} to avoid exception chaining.
@arg inst: An error instance (C{Exception}). @kwarg other: The previous error instance (C{Exception}) or C{None} to avoid exception chaining.
@see: Alex Martelli, et.al., "Python in a Nutshell", 3rd Ed., page 163, O'Reilly, 2017, U{PEP-3134<https://www.Python.org/dev/peps/pep-3134>}, U{here <https://StackOverflow.com/questions/17091520/how-can-i-more- easily-suppress-previous-exceptions-when-i-raise-my-own-exception>} and U{here<https://StackOverflow.com/questions/1350671/ inner-exception-with-traceback-in-python>}. '''
except AttributeError: # Python 2+
def _error_chain(inst, **unused): # PYCHOK expected return inst # no-op
'''(INTERNAL) Format an C{AssertionError} without exception chaining. '''
'''(INTERNAL) Format an C{AttributeError} without exception chaining. '''
'''(INTERNAL) Format an C{ImportError} without exception chaining. '''
'''(INTERNAL) Format an C{IndexError} without exception chaining. '''
'''(INTERNAL) Format a C{NameError} without exception chaining. '''
'''(INTERNAL) Format a C{NotImplementedError} without exception chaining. '''
'''(INTERNAL) Format an C{OverflowError} without exception chaining. '''
'''(INTERNAL) Format a C{TypeError} without exception chaining. ''' **txt_name_values)
'''(INTERNAL) Format a C{TypeError} without exception chaining. '''
'''(INTERNAL) Format a C{ValueError} without exception chaining. '''
'''Error raised for zero or near-zero vectorial cross products, occurring for coincident or colinear points, paths or bearings. '''
'''Error raised for path or circle intersection issues. ''' '''New L{IntersectionError}. ''' else:
'''Error raised for mis-matching C{len} values. ''' '''New L{LenError}.
@arg where: Object with C{.__name__} attribute (C{class}, C{method}, or C{function}). @kwarg lens_txt: Two or more C{name=len(name)} pairs (C{keyword arguments}). '''
'''Error raised for lat- or longitudinal deltas exceeding the B{C{limit}} in functions L{pygeodesy.equirectangular} and L{pygeodesy.equirectangular_} and several C{nearestOn*} and C{simplify*} functions or methods. '''
'''Error raised for C{NumPy} errors. '''
'''Error parsing degrees, radians or several other formats. '''
'''Error for an insufficient number of points. '''
'''Error raised for lat- or longitude values outside the B{C{clip}}, B{C{clipLat}}, B{C{clipLon}} or B{C{limit}} range in function L{pygeodesy.clipDegrees}, L{pygeodesy.clipRadians}, L{pygeodesy.parse3llh}, L{pygeodesy.parseDMS}, L{pygeodesy.parseDMS2} or L{pygeodesy.parseRad}.
@see: Function L{pygeodesy.rangerrors}. '''
'''Error raised for resection issues. '''
'''Error raised for triangle, inter- or resection issues. '''
'''Error raised for C{SciPy} errors. '''
'''Error thrown for C{SciPy} warnings.
To raise C{SciPy} warnings as L{SciPyWarning} exceptions, Python C{warnings} must be filtered as U{warnings.filterwarnings('error') <https://docs.Python.org/3/library/warnings.html#the-warnings-filter>} I{prior to} C{import scipy} or by setting environment variable U{PYTHONWARNINGS<https://docs.Python.org/3/using/cmdline.html #envvar-PYTHONWARNINGS>} or with C{python} command line option U{-W<https://docs.Python.org/3/using/cmdline.html#cmdoption-w>} as C{error}. '''
'''Terrestrial Reference Frame (TRF), L{Epoch}, L{RefFrame} or L{RefFrame} conversion issue. '''
'''Default exception for L{units} issues. '''
'''L{Vector3d}, C{Cartesian*} or C{*Nvector} issues. '''
'''(INTERNAL) Prepend an article to a noun based on the pronounciation of the first letter. '''
'''(INTERNAL) Join C{words} with C{", "} and C{" and "}. '''
'''Report or ignore vectorial cross product errors.
@kwarg raiser: Use C{True} to throw or C{False} to ignore L{CrossError} exceptions. Use C{None} to leave the setting unchanged.
@return: Previous setting (C{bool}).
@see: Property C{Vector3d[Base].crosserrors}. '''
'''(INTERNAL) Check for datum or ellipsoid match. ''' raise Error(E2.named2, txt=_incompatible(E1.named2)) t = _SPACE_(_datum_, repr(datum1.name), _not_, repr(datum2.name)) raise _AssertionError(t)
txt=_invalid_, **name_values): # by .lazily '''(INTERNAL) Format an error text and initialize an C{Error} instance.
@arg Error: The error super-class (C{Exception}). @arg inst: Sub-class instance to be initialized (C{_Exception}). @arg name_value: Either just a value or several name, value, ... positional arguments (C{str}, any C{type}), in particular for name conflicts with keyword arguments of C{error_init} or which can't be used as C{name=value} keyword arguments. @kwarg fmt_name_value: Format for (name, value) (C{str}). @kwarg txt: Optional explanation of the error (C{str}). @kwarg name_values: One or more C{B{name}=value} pairs overriding any B{C{name_value}} positional arguments. ''' name_value[1::2]))) else:
# else: # x = NN # XXX or t? # inst.__x_txt__ = x # hold explanation
'''(INTERNAL) Remove leading underscore from instance' class name. '''
'''Get the previous exception's or exception chaining setting.
@kwarg error: An error instance (C{Exception}) or C{None}.
@return: If C{B{error} is None}, return C{True} if exception chaining is enabled for PyGeodesy errors, C{False} if turned off and C{None} if not available. If B{C{error}} is not C{None}, return the previous, chained error or C{None} otherwise.
@note: Set C{env} variable C{PYGEODESY_EXCEPTION_CHAINING} to any non-empty value prior to C{import pygeodesy} to enable exception chaining for C{pygeodesy} errors. ''' getattr(error, '__cause__', None)
'''(INTERNAL) Format an incompatible text. '''
'''(INTERNAL) Create an C{Error} instance.
@kwarg Error: The error class or sub-class (C{Exception}). @kwarg txt_name_values: One or more C{B{name}=value} pairs and optionally, a C{B{txt}=...} keyword argument to override the default C{B{txt}='invalid'}
@return: An B{C{Error}} instance. ''' except TypeError: # std *Error takes no keyword arguments e = _ValueError(**txt_name_values) e = Error(str(e)) _error_chain(e) _error_under(e)
'''Create a C{TypeError} for an invalid C{name=value} type.
@arg nouns: One or more expected class or type names, usually nouns (C{str}). @kwarg name_value_Error: One C{B{name}=value} pair and optionally, an C{B{Error}=...} keyword argument to override the default C{B{Error}=TypeError}.
@return: A C{TypeError} or an B{C{Error}} instance. ''' _name_value_, MISSING) # XXX else tuple(...)
'''Get/set the throwing of L{LimitError}s.
@kwarg raiser: Choose C{True} to raise or C{False} to ignore L{LimitError} exceptions. Use C{None} to leave the setting unchanged.
@return: Previous setting (C{bool}). ''' global _limiterrors
'''(INTERNAL) Join C{words} with C{", "} and C{" or "}. '''
'''(INTERNAL) Invoke a parser and handle exceptions.
@arg parser: The parser (C{callable}). @arg args: Any parser positional arguments (any C{type}s). @kwarg name_values_Error: One or more C{B{name}=value} pairs and optionally, an C{B{Error}=...} keyword argument to override the default C{B{Error}=ParseError}.
@return: Parser result.
@raise ParseError: Or the specified C{B{Error}=...}.
@raise RangeError: If that error occurred. '''
except RangeError as x: t = str(x) E = type(x) _ = _xkwds_pop(name_values_Error, Error=None) except (AttributeError, IndexError, TypeError, ValueError) as x: t = str(x) E = _xkwds_pop(name_values_Error, Error=ParseError) raise _InvalidError(Error=E, txt=t, **name_values_Error)
'''Get/set the throwing of L{RangeError}s.
@kwarg raiser: Choose C{True} to raise or C{False} to ignore L{RangeError} exceptions. Use C{None} to leave the setting unchanged.
@return: Previous setting (C{bool}). ''' global _rangerrors
def _SciPyIssue(x, *extras): # PYCHOK no cover if isinstance(x, (RuntimeWarning, UserWarning)): X = SciPyWarning else: X = SciPyError # PYCHOK not really t = _SPACE_(str(x).strip(), *extras) return _error_chain(X(t), other=x)
'''(INTERNAL) Check an I{ellipsoidal} item.
@return: The B{C{value}} if ellipsoidal.
@raise TypeError: Not ellipsoidal B{C{value}}. ''' break else: n = v = MISSING except AttributeError: pass raise _TypeError(n, v, txt=_not_(_ellipsoidal_))
'''(INTERNAL) Embellish an exception.
@arg x: The exception instance (usually, C{_Error}). @arg kwds: Embelishments (C{any}). ''' except TypeError: # no keyword arguments pass # not an C{_Error}, format as C{_Error} t = str(_ValueError(txt=t, *name_value, **kwds)) return x if _exception_chaining else X(t)
'''(INTERNAL) Override C{dflts} with specified C{kwds}. '''
except AttributeError:
from copy import copy as _copy
def _xkwds(kwds, **dflts): # PYCHOK expected '''(INTERNAL) Override C{dflts} with specified C{kwds}. ''' d = dflts if kwds: d = _copy(d) d.update(kwds) return d
# Helper for _xkwds_get, _xkwds_pop and _xkwds_popitem below
'''(INTERNAL) Get a C{kwds} value by C{name}, or the C{default}. '''
raise _xkwds_Error(_xkwds_get, kwds, name_default)
'''(INTERNAL) Return C{kwds} with a value not in C{args}. '''
'''(INTERNAL) Pop a C{kwds} value by C{name}, or the C{default}. '''
raise _xkwds_Error(_xkwds_pop, kwds, name_default)
'''(INTERNAL) Return exactly one C{(name, value)} item. '''
raise _xkwds_Error(_xkwds_popitem, (), name_value, txt=_value_)
# **) 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. |