Coverage for pygeodesy/named.py : 95%

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 -*-
all with nameable instances and several subclasses thereof.
In addition, the items in a C{_NamedDict} are accessable as attributes and the items in a C{_NamedTuple} can be named to be accessable as attributes, similar to standard Python C{namedtuple}s.
Results previously returned as tuples by C{pygeodesy} functions and class methods are now instances of some C{...Tuple} class, all sub-classes of C{_NamedTuple} defined here.
@newfield example: Example, Examples '''
# update imported names under if __name__ == '__main__': property_doc_, property_RO, _xcopy
# XXX 'FsumDelta2Tuple' is in _ALL_LAZY.named '_NamedBase', # '_NamedDict', '_NamedEnum', '_NamedEnumItem', # '_NamedTuple', 'Bearing2Tuple', 'Bounds2Tuple', 'Bounds4Tuple', 'Destination2Tuple', 'Destination3Tuple', 'Distance2Tuple', 'Distance3Tuple', 'Distance4Tuple', 'EasNor2Tuple', 'EasNor3Tuple', 'LatLon2Tuple', 'LatLon3Tuple', 'LatLon4Tuple', 'LatLonDatum3Tuple', 'LatLonPrec3Tuple', 'LatLonPrec5Tuple', 'NearestOn3Tuple', 'PhiLam2Tuple', 'PhiLam3Tuple', 'PhiLam4Tuple', 'Points2Tuple', 'Vector3Tuple', 'Vector4Tuple', 'notOverloaded')
'''(INTERNAL) Set the instance' C{.name = }B{C{name}}.
@arg inst: The instance (C{_Named}). @arg name: The name (C{str}).
@return: The B{C{inst}}, named if not named before. '''
'''(INTERNAL) Root class for named objects. '''
'''Default C{repr(self)}. '''
'''Default C{str(self)}. '''
'''Join attributes as C{name=value} pairs.
@arg names: The attribute names (C{str}s). @kwarg kwds: Keyword argument for function L{attrs}.
@return: All C{name=value} pairs joined (C{str}). '''
def classname(self): '''Get this object's C{[module.]class} name (C{str}), see property C{.classnaming} and function C{classnaming}. '''
def classnaming(self): '''Get the class naming (C{bool}), see function C{classnaming}. '''
def classnaming(self, prefixed): '''Set the class naming for C{[module.].class} names.
@arg prefixed: Include the module name (C{bool}). '''
'''Create another instance of this very class.
@arg args: Optional, positional arguments. @kwarg kwds: Optional, keyword arguments.
@return: New instance (B{self.__class__}). '''
'''Make a shallow or deep copy of this instance.
@kwarg deep: If C{True} make a deep, otherwise a shallow copy (C{bool}).
@return: The copy (C{This class} or subclass thereof). '''
'''(INTERNAL) Period-join C{self.name} and C{name}. '''
def name(self): '''Get the name (C{str}). '''
def name(self, name): '''Set the name.
@arg name: New name (C{str}). ''' # to set the name from a sub-class, use # self.name = name or # _Named.name.fset(self, name), but not # _Named(self).name = name
def named(self): '''Get the name I{or} class name or C{""} (C{str}). '''
def named2(self): '''Get the class name I{and/or} the name or C{""} (C{str}). '''
'''Default C{repr(self)}. '''
'''DEPRECATED, used method C{toRepr}.'''
'''Default C{str(self)}. ''' return str(self)
'''(INTERNAL) Set the instance' C{.name = self.name}.
@arg inst: The instance (C{_Named}). @kwarg name: Optional name, overriding C{self.name} (C{str}).
@return: The B{C{inst}}, named if not named before. '''
'''(INTERNAL) Rename the instance' C{.name = self.name}.
@arg inst: The instance (C{_Named}).
@return: The B{C{inst}}, named if not named before. ''' raise IsnotError('valid', inst=inst)
inst.name = self.name
'''(INTERNAL) Base class with name. '''
'''(INTERNAL) Zap cached instance attributes. ''' raise AttributeError('.%s invalid: %r' % (a, self))
# def notImplemented(self, attr): # '''Raise error for a missing method, function or attribute. # # @arg attr: Attribute name (C{str}). # # @raise NotImplementedError: No such attribute. # ''' # c = self.__class__.__name__ # return NotImplementedError(_dot_(c, attr))
'''Check this and an other instance for type compatiblility.
@arg other: The other instance (any C{type}). @kwarg name: Optional, name for other (C{str}).
@raise TypeError: Mismatch of the B{C{other}} and this C{class} or C{type}. ''' isinstance(other, self.__class__)): raise TypeError('%s mismatch: %s vs %s' % (name, classname(other), self.classname))
'''(INTERNAL) To be overloaded.
@kwarg kwds: Optional, keyword arguments.
@return: C{toStr}() with keyword arguments (as C{str}). '''
# def toRepr(self, **kwds) # if kwds: # s = ''.join(reprs((self,), **kwds)) # else: # super().__repr__ only for Python 3+ # s = super(self.__class__, self).__repr__() # return '%s(%s)' % (self.named, s) # clips(s)
def toStr(self, **kwds): # PYCHOK no cover '''(INTERNAL) Must be overloaded.
@raise AssertionError: Always, see function L{notOverloaded}. ''' notOverloaded(self, self.toStr, **kwds)
# def toStr(self, **kwds): # if kwds: # s = ''.join(strs((self,), **kwds)) # else: # super().__str__ only for Python 3+ # s = super(self.__class__, self).__str__() # return s
'''(INTERNAL) Named C{dict} with key I{and} attribute access to the items. '''
t = unstr(self.classname, *args, **kwds) raise ValueError('invalid: ' + t)
dict.pop(name) else:
return _Named.name.fget(self)
raise KeyError('%s[%r]' % (self.classname, key))
dict.__setitem__(self, name, value) # self[name] = value else:
raise KeyError('%s[%r] = %r' % (self.classname, key, value))
'''Like C{repr(dict)} but with C{name} and C{floats} formatting by C{fstr}. '''
'''DEPRECATED, use method C{toRepr}.'''
'''Like C{str(dict)} but with C{floats} formatting by C{fstr}. '''
'''(INTERNAL) Enum-like C{_NamedDict} with attribute access restricted to valid keys. '''
'''New C{_NamedEnum}.
@arg name: Name (C{str}). '''
return _NamedDict.name.fget(self) raise AttributeError("%s doesn't exist" % (self._dot_(name),))
'''(INTERNAL) Check names against given, registered names. ''' and self.find(v) == a
'''Find a registered item.
@arg item: The item to look for (any C{type}).
@return: If found the B{C{item}}'s name (C{str}), C{None} otherwise. '''
'''Registed a new item.
@arg item: The item (any C{type}).
@return: The item name (C{str}).
@raise NameError: An B{C{item}} already registered with that name or the B{C{item}} has no, an empty or an invalid name.
@raise TypeError: The B{C{item}} type invalid. ''' raise TypeError('%s: %r' % (_dot_('item', 'type'), item))
raise ValueError except (AttributeError, ValueError): raise NameError('%s %s: %r' % (_dot_('item', 'name'), 'invalid', item)) raise NameError('%s %s: %r' % (self._dot_(n), 'exists', item))
'''Remove a registered item.
@arg name_or_item: Name (C{str}) of or the item (any C{type}).
@return: The unregistered item.
@raise NameError: No item with that B{C{name}}.
@raise ValueError: No such item. ''' raise ValueError('no such %r' % (name_or_item,)) except KeyError: raise NameError('no %r' % (self._dot_(name),))
'''Like C{repr(dict)} but with C{name} and C{floats} formatting by C{fstr}. '''
'''DEPRECATED, use method C{toRepr}.'''
'''Like C{str(dict)} but with C{floats} formatting by C{fstr}. '''
'''(INTERNAL) Base class for items in a C{_NamedEnum} registery. '''
'''Compare this and an other item.
@return: C{True} if different, C{False} otherwise. '''
'''(INTERNAL) Format, used by C{Conic}, C{Ellipsoid}, C{Transform}. ''' prec=prec, ints=True)
def name(self): '''Get the I{registered} name (C{str}). '''
def name(self, name): '''Set the name, unless already registered.
@arg name: New name (C{str}). ''' raise ValueError('%s, %s: %r' % ('registered', 'immutable', self))
'''(INTERNAL) Add this item as B{C{enum.name}}.
@note: Don't register if name is empty or doesn't start with a letter. '''
'''Remove this instance from its C{_NamedEnum} registry.
@raise AssertionError: Mismatch of this and registered item.
@raise NameError: This item is unregistered. ''' raise AssertionError('%r vs %r' % (item, self))
'''(INTERNAL) Named C{tuple} with index I{and} attribute access to the items.
@note: This class is similar to Python's C{namedtuple}, but limited and lighter in setup and weight. '''
'''New L{_NamedTuple} initialized with B{C{positional}} arguments. ''' raise TypeError('%s invalid: %r' % (_dot_( self.classname, '_Names_'), ns)) raise ValueError('%s(%s) invalid: %r[%s] vs %s' % (self.classname, 'args', args, len(args), len(ns))) raise NameError('%s invalid: %r' % (_dot_( self.classname, '_Names_'), _NAME_))
raise TypeError('%s not mutable: %s .%s' % (self.classname, 'del', name)) else: tuple.__delattr__(self, name)
raise IndexError('%s not valid: %r' % (_dot_( self.classname, '<name>'), name))
raise TypeError('%s not mutable: %s=%r' % (self.classname, name, value)) else:
'''Get the items as C{name, value} pairs (C{2-tuple}s). '''
'''(INTERNAL) Extend this C{_Tuple} with C{items} to an other C{NamedTuple}. ''' (len(self._Names_) + len(items)) == len(NamedTuple._Names_) and self._Names_ == NamedTuple._Names_[:len(self)]): raise TypeError('%s%r vs %s%r' % (self.classname, self._Names_, NamedTuple.__name__, NamedTuple._Names_))
'''Return the -Tuple items as C{name=value} string(s).
@kwarg prec: The C{float} precision, number of decimal digits (0..9). Trailing zero decimals are stripped for B{C{prec}} values of 1 and above, but kept for negative B{C{prec}} values. @kwarg sep: Optional separator to join (C{str}).
@return: Tuple items (C{str}). '''
'''DEPRECATED, use method C{toRepr}.'''
'''Return the -Tuple items as string(s).
@kwarg prec: The C{float} precision, number of decimal digits (0..9). Trailing zero decimals are stripped for B{C{prec}} values of 1 and above, but kept for negative B{C{prec}} values. @kwarg sep: Optional separator to join (C{str}).
@return: Tuple items (C{str}). '''
'''2-Tuple C{(initial, final)} bearings, both in compass C{degrees360}. '''
'''2-Tuple C{(latlonSW, latlonNE)} with the bounds' lower-left and upper-right corner as C{LatLon} instance. '''
'''4-Tuple C{(latS, lonW, latN, lonE)} with the bounds' lower-left C{(LatS, LowW)} and upper-right C{(latN, lonE)} corner lat- and longitudes. '''
'''2-Tuple C{(destination, final)}, C{destination} in C{LatLon} and C{final} bearing in compass C{degrees360}. '''
'''3-Tuple C{(lat, lon, final)}, destination C{lat}, C{lon} in and C{final} bearing in C{degrees}. '''
'''2-Tuple C{(distance, initial)}, C{distance} in C{meter} and C{initial} bearing in compass C{degrees360}. '''
'''3-Tuple C{(distance, initial, final)}, C{distance} in C{meter} and C{initial} and C{final} bearing, both in compass C{degrees360}. '''
'''4-Tuple C{(distance2, delta_lat, delta_lon, unroll_lon2)} with the distance in C{degrees squared}, the latitudinal C{delta_lat} = B{C{lat2}}-B{C{lat1}}, the wrapped, unrolled and adjusted longitudinal C{delta_lon} = B{C{lon2}}-B{C{lon1}} and the C{unroll_lon2} unrollment for B{C{lon2}}.
@note: Use Function L{degrees2m} to convert C{degrees squared} to C{meter} as M{degrees2m(sqrt(distance2), ...)} or M{degrees2m(hypot(delta_lat, delta_lon), ...)}. '''
'''2-Tuple C{(easting, northing)}, both in C{meter}. '''
'''3-Tuple C{(easting, northing, height)}, all in C{meter}. '''
'''2-Tuple C{(lat, lon)} in C{degrees90} and C{degrees180}. '''
'''Extend this L{LatLon2Tuple} to a L{LatLon3Tuple}.
@arg height: The height to add (C{scalar}).
@return: A L{LatLon3Tuple}C{(lat, lon, height)}.
@raise ValueError: Invalid B{C{height}}. '''
'''Extend this L{LatLon2Tuple} to a L{LatLon4Tuple}.
@arg height: The height to add (C{scalar}). @arg datum: The datum to add (C{Datum}).
@return: A L{LatLon4Tuple}C{(lat, lon, height, datum)}.
@raise TypeError: If B{C{datum}} not a C{Datum}.
@raise ValueError: Invalid B{C{height}}. '''
'''3-Tuple C{(lat, lon, height)} in C{degrees90}, C{degrees180} and C{meter}. '''
'''Extend this L{LatLon3Tuple} to a L{LatLon4Tuple}.
@arg datum: The datum to add (C{Datum}).
@return: A L{LatLon4Tuple}C{(lat, lon, height, datum)}.
@raise TypeError: If B{C{datum}} not a C{Datum}. ''' raise IsnotError(Datum.__name__, datum=datum)
'''4-Tuple C{(lat, lon, height, datum)} in C{degrees90}, C{degrees180}, C{meter} and L{Datum}. '''
'''3-Tuple C{(lat, lon, datum)} in C{degrees90}, C{degrees180} and L{Datum}. '''
'''3-Tuple C{(lat, lon, precision)} in C{degrees}, C{degrees} and C{int}. '''
'''5-Tuple C{(lat, lon, precision, height, radius)} in C{degrees}, C{degrees}, C{int} and C{height} or C{radius} in C{meter} (or C{None} if missing). '''
'''3-Tuple C{(closest, distance, angle)} of the C{closest} point on the polygon, either a C{LatLon} instance or a L{LatLon3Tuple}C{(lat, lon, height)} and the C{distance} and C{angle} to the C{closest} point are in C{meter} respectively compass C{degrees360}. '''
'''2-Tuple C{(phi, lam)} with latitude C{phi} in C{radians[PI_2]} and longitude C{lam} in C{radians[PI]}.
@note: Using C{phi/lambda} for lat-/longitude in C{radians} follows Chris Veness' U{convention <https://www.Movable-Type.co.UK/scripts/latlong.html>}. '''
'''Extend this L{PhiLam2Tuple} to a L{PhiLam3Tuple}.
@arg height: The height to add (C{scalar}).
@return: A L{PhiLam3Tuple}C{(phi, lam, height)}.
@raise ValueError: Invalid B{C{height}}. '''
'''Extend this L{PhiLam2Tuple} to a L{PhiLam4Tuple}.
@arg height: The height to add (C{scalar}). @arg datum: The datum to add (C{Datum}).
@return: A L{PhiLam4Tuple}C{(phi, lam, height, datum)}.
@raise TypeError: If B{C{datum}} not a C{Datum}.
@raise ValueError: Invalid B{C{height}}. ''' return self.to3Tuple(height).to4Tuple(datum)
'''3-Tuple C{(phi, lam, height)} with latitude C{phi} in C{radians[PI_2]}, longitude C{lam} in C{radians[PI]} and C{height} in C{meter}.
@note: Using C{phi/lambda} for lat-/longitude in C{radians} follows Chris Veness' U{convention <https://www.Movable-Type.co.UK/scripts/latlong.html>}. '''
'''Extend this L{PhiLam3Tuple} to a L{PhiLam4Tuple}.
@arg datum: The datum to add (C{Datum}).
@return: A L{PhiLam4Tuple}C{(phi, lam, height, datum)}.
@raise TypeError: If B{C{datum}} not a C{Datum}. ''' raise IsnotError(Datum.__name__, datum=datum)
'''4-Tuple C{(phi, lam, height, datum)} with latitude C{phi} in C{radians[PI_2]}, longitude C{lam} in C{radians[PI]}, C{height} in C{meter} and L{Datum}.
@note: Using C{phi/lambda} for lat-/longitude in C{radians} follows Chris Veness' U{convention <https://www.Movable-Type.co.UK/scripts/latlong.html>}. '''
'''2-Tuple C{(number, points)} with the C{number} of points and -possible reduced- C{list} or C{tuple} of C{points}. '''
'''3-Tuple C{(x, y, z)} of (geocentric) components, all in C{meter} or C{units}. '''
'''Extend this L{Vector3Tuple} to a L{Vector4Tuple}.
@arg h: The height to add (C{scalar}).
@return: A L{Vector4Tuple}C{(x, y, z, h)}.
@raise ValueError: Invalid B{C{h}}. '''
'''4-Tuple C{(x, y, z, h)} of (geocentric) components, all in C{meter} or C{units}. '''
'''Return the instance' class name optionally prefixed with the module name.
@arg inst: The object (any C{type}). @kwarg prefixed: Include the module name (C{bool}), see function C{classnaming}.
@return: The B{C{inst}}'s C{[module.]class} name (C{str}). ''' (getattr(inst, 'classnaming', classnaming()) if prefixed is None else False))
'''Get/set the default class naming for C{[module.]class} names.
@kwarg prefixed: Include the module name (C{bool}).
@return: Previous class naming setting (C{bool}). '''
'''Return the class name optionally prefixed with the module name.
@arg clas: The class (any C{class}). @kwarg prefixed: Include the module name (C{bool}), see function C{classnaming}.
@return: The B{C{class}}'s C{[module.]class} name (C{str}). ''' except AttributeError: n = '--' except AttributeError: pass
'''Get the name of an instance.
@arg inst: The object (any C{type}).
@return: The instance' name (C{str}) or C{""}. '''
def notOverloaded(inst, name, *args, **kwds): # PYCHOK no cover '''Raise an C{AssertionError} for a method or property not overloaded.
@arg name: Method, property or name (C{str}). @arg args: Method or property positional arguments (any C{type}s). @arg kwds: Method or property keyword arguments (any C{type}s). ''' n = getattr(name, '__name__', name) n = '%s %s' % (notOverloaded.__name__, _dot_(classname(inst, prefixed=True), n)) m = ', '.join(modulename(c, prefixed=True) for c in inst.__class__.__mro__[1:-1]) raise AssertionError('%s, MRO(%s)' % (unstr(n, *args, **kwds), m))
if __name__ == '__main__':
import sys
from pygeodesy.lazily import _FOR_DOCS
if not _FOR_DOCS: sys.exit('%s\n' % (' '.join('usage: env PYGEODESY_FOR_DOCS=1 python -m'.split() + sys.argv),))
ls = locals() for n in __all__: if n not in ls: raise NameError('%s %r not in %s' % ('__all__', n, _dot_('named', 'locals'))) for n, o in ls.items(): if n not in __all__ and not n.startswith('_') \ and getattr(o, '__module__', '') == __name__: raise NameError('%s %r not in %s' % ('locals', n, _dot_('named', '__all__')))
print('%s: %s vs %s OK' % (sys.argv[0], '__all__', 'locals'))
# **) MIT License # # Copyright (C) 2016-2020 -- 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.
# % env PYGEODESY_FOR_DOCS=1 python -m pygeodesy.named # all 71 locals OK |