pygeodesy 25.4.8__py2.py3-none-any.whl → 25.5.5__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. pygeodesy/__init__.py +36 -31
  2. pygeodesy/__main__.py +3 -3
  3. pygeodesy/albers.py +29 -36
  4. pygeodesy/auxilats/_CX_4.py +2 -2
  5. pygeodesy/auxilats/_CX_6.py +2 -2
  6. pygeodesy/auxilats/_CX_8.py +2 -2
  7. pygeodesy/auxilats/_CX_Rs.py +9 -9
  8. pygeodesy/auxilats/__init__.py +3 -3
  9. pygeodesy/auxilats/__main__.py +8 -6
  10. pygeodesy/auxilats/auxAngle.py +2 -2
  11. pygeodesy/auxilats/auxLat.py +5 -5
  12. pygeodesy/auxilats/auxily.py +5 -3
  13. pygeodesy/azimuthal.py +7 -6
  14. pygeodesy/basics.py +32 -18
  15. pygeodesy/booleans.py +18 -16
  16. pygeodesy/cartesianBase.py +26 -24
  17. pygeodesy/clipy.py +11 -10
  18. pygeodesy/constants.py +11 -10
  19. pygeodesy/css.py +14 -11
  20. pygeodesy/datums.py +8 -8
  21. pygeodesy/deprecated/bases.py +2 -2
  22. pygeodesy/deprecated/classes.py +2 -2
  23. pygeodesy/deprecated/consterns.py +4 -4
  24. pygeodesy/dms.py +8 -8
  25. pygeodesy/ecef.py +22 -29
  26. pygeodesy/ecefLocals.py +186 -0
  27. pygeodesy/elevations.py +9 -8
  28. pygeodesy/ellipsoidalBase.py +19 -8
  29. pygeodesy/ellipsoidalBaseDI.py +17 -15
  30. pygeodesy/ellipsoidalNvector.py +6 -3
  31. pygeodesy/ellipsoidalVincenty.py +4 -1
  32. pygeodesy/ellipsoids.py +186 -164
  33. pygeodesy/elliptic.py +9 -9
  34. pygeodesy/errors.py +44 -43
  35. pygeodesy/etm.py +7 -7
  36. pygeodesy/fmath.py +30 -14
  37. pygeodesy/formy.py +11 -12
  38. pygeodesy/frechet.py +216 -109
  39. pygeodesy/fstats.py +5 -4
  40. pygeodesy/fsums.py +79 -78
  41. pygeodesy/gars.py +4 -3
  42. pygeodesy/geodesici.py +15 -14
  43. pygeodesy/geodesicw.py +34 -32
  44. pygeodesy/geodesicx/__init__.py +1 -1
  45. pygeodesy/geodesicx/__main__.py +11 -9
  46. pygeodesy/geodesicx/gx.py +30 -33
  47. pygeodesy/geodesicx/gxarea.py +2 -2
  48. pygeodesy/geodesicx/gxline.py +5 -5
  49. pygeodesy/geodsolve.py +18 -17
  50. pygeodesy/geohash.py +5 -5
  51. pygeodesy/geoids.py +34 -31
  52. pygeodesy/hausdorff.py +17 -13
  53. pygeodesy/heights.py +2 -4
  54. pygeodesy/internals.py +28 -44
  55. pygeodesy/interns.py +10 -7
  56. pygeodesy/iters.py +8 -8
  57. pygeodesy/karney.py +68 -62
  58. pygeodesy/ktm.py +5 -5
  59. pygeodesy/latlonBase.py +20 -21
  60. pygeodesy/lazily.py +104 -78
  61. pygeodesy/lcc.py +11 -9
  62. pygeodesy/ltp.py +56 -58
  63. pygeodesy/ltpTuples.py +35 -36
  64. pygeodesy/mgrs.py +7 -6
  65. pygeodesy/named.py +48 -177
  66. pygeodesy/nvectorBase.py +7 -7
  67. pygeodesy/osgr.py +9 -8
  68. pygeodesy/points.py +12 -10
  69. pygeodesy/props.py +25 -25
  70. pygeodesy/resections.py +83 -80
  71. pygeodesy/rhumb/__init__.py +1 -1
  72. pygeodesy/rhumb/aux_.py +7 -7
  73. pygeodesy/rhumb/bases.py +22 -20
  74. pygeodesy/rhumb/ekx.py +6 -6
  75. pygeodesy/rhumb/solve.py +15 -15
  76. pygeodesy/solveBase.py +3 -3
  77. pygeodesy/sphericalBase.py +6 -6
  78. pygeodesy/sphericalNvector.py +6 -5
  79. pygeodesy/sphericalTrigonometry.py +8 -7
  80. pygeodesy/streprs.py +14 -14
  81. pygeodesy/trf.py +14 -12
  82. pygeodesy/triaxials.py +29 -26
  83. pygeodesy/units.py +5 -4
  84. pygeodesy/unitsBase.py +5 -4
  85. pygeodesy/ups.py +3 -3
  86. pygeodesy/utily.py +4 -4
  87. pygeodesy/utmups.py +4 -4
  88. pygeodesy/utmupsBase.py +110 -18
  89. pygeodesy/vector2d.py +20 -13
  90. pygeodesy/vector3d.py +7 -6
  91. pygeodesy/webmercator.py +6 -5
  92. pygeodesy/wgrs.py +6 -5
  93. {pygeodesy-25.4.8.dist-info → pygeodesy-25.5.5.dist-info}/METADATA +30 -25
  94. pygeodesy-25.5.5.dist-info/RECORD +119 -0
  95. pygeodesy-25.4.8.dist-info/RECORD +0 -118
  96. {pygeodesy-25.4.8.dist-info → pygeodesy-25.5.5.dist-info}/WHEEL +0 -0
  97. {pygeodesy-25.4.8.dist-info → pygeodesy-25.5.5.dist-info}/top_level.txt +0 -0
pygeodesy/geoids.py CHANGED
@@ -89,7 +89,8 @@ courtesy of SBFRF.
89
89
  # make sure int/int division yields float quotient, see .basics
90
90
  from __future__ import division as _; del _ # PYCHOK semicolon
91
91
 
92
- from pygeodesy.basics import len2, min2, isodd, _splituple, ub2str as _ub2str
92
+ from pygeodesy.basics import _isin, len2, min2, isodd, _splituple, \
93
+ ub2str as _ub2str
93
94
  from pygeodesy.constants import EPS, _float as _F, _1_0, _N_90_0, _180_0, \
94
95
  _N_180_0, _360_0
95
96
  from pygeodesy.datums import Datums, _ellipsoidal_datum, _WGS84
@@ -100,10 +101,10 @@ from pygeodesy.fmath import favg, Fdot, fdot, Fhorner, frange
100
101
  # from pygoedesy.formy import heightOrthometric # _MODS
101
102
  from pygeodesy.heights import _as_llis2, _ascalar, _HeightBase, HeightError, \
102
103
  _Wrap
103
- # from pygeodesy.internals import _version2 # _MODS
104
- from pygeodesy.interns import NN, _COLONSPACE_, _COMMASPACE_, _E_, _height_, \
105
- _in_, _kind_, _lat_, _lon_, _mean_, _N_, _n_a_, \
106
- _numpy_, _on_, _outside_, _S_, _s_, _scipy_, \
104
+ # from pygeodesy.internals import typename, _version2 # _MODS
105
+ from pygeodesy.interns import NN, _COLONSPACE_, _COMMASPACE_, _DMAIN_, _E_, \
106
+ _height_, _in_, _kind_, _lat_, _lon_, _mean_, _N_, \
107
+ _n_a_, _numpy_, _on_, _outside_, _S_, _s_, _scipy_, \
107
108
  _SPACE_, _stdev_, _tbd_, _W_, _width_, _4_
108
109
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS, _FOR_DOCS
109
110
  from pygeodesy.named import _name__, _Named, _NamedTuple
@@ -125,7 +126,7 @@ except ImportError: # Python 3+
125
126
  from io import BytesIO as _BytesIO # PYCHOK expected
126
127
 
127
128
  __all__ = _ALL_LAZY.geoids
128
- __version__ = '25.01.15'
129
+ __version__ = '25.04.14'
129
130
 
130
131
  _assert_ = 'assert'
131
132
  _bHASH_ = b'#'
@@ -571,7 +572,7 @@ class _GeoidBase(_HeightBase):
571
572
  except (IOError, OSError) as x:
572
573
  raise GeoidError(geoid=geoid, cause=x)
573
574
 
574
- if datum not in (None, self._datum):
575
+ if not _isin(datum, None, self._datum):
575
576
  self._datum = _ellipsoidal_datum(datum, name=name)
576
577
  self._kind = int(kind)
577
578
  if name:
@@ -651,15 +652,16 @@ class _GeoidBase(_HeightBase):
651
652
 
652
653
  @return: Geoid name and attributes (C{str}).
653
654
  '''
654
- s = 1 if self.kind < 0 else 2
655
- t = tuple(Fmt.PAREN(m.__name__, fstr(m(), prec=prec)) for m in
656
- (self.lowerleft, self.upperright,
657
- self.center,
658
- self.highest, self.lowest)) + \
659
- attrs( _mean_, _stdev_, prec=prec, Nones=False) + \
660
- attrs((_kind_, 'smooth')[:s], prec=prec, Nones=False) + \
661
- attrs( 'cropped', 'dtype', _endian_, 'hits', 'knots', 'nBytes',
662
- 'sizeB', _scipy_, _numpy_, prec=prec, Nones=False)
655
+ s = 1 if self.kind < 0 else 2
656
+ t = _MODS.internals.typename
657
+ t = tuple(Fmt.PAREN(t(m), fstr(m(), prec=prec)) for m in
658
+ (self.lowerleft, self.upperright,
659
+ self.center,
660
+ self.highest, self.lowest)) + \
661
+ attrs( _mean_, _stdev_, prec=prec, Nones=False) + \
662
+ attrs((_kind_, 'smooth')[:s], prec=prec, Nones=False) + \
663
+ attrs( 'cropped', 'dtype', _endian_, 'hits', 'knots', 'nBytes',
664
+ 'sizeB', _scipy_, _numpy_, prec=prec, Nones=False)
663
665
  return _COLONSPACE_(self, sep.join(t))
664
666
 
665
667
  @Property_RO
@@ -1036,9 +1038,9 @@ class GeoidKarney(_GeoidBase):
1036
1038
  if smooth is not None:
1037
1039
  raise GeoidError(smooth=smooth, txt_not_=_supported_)
1038
1040
 
1039
- if kind in (2,):
1041
+ if _isin(kind, 2):
1040
1042
  self._ev2d = self._ev2k # see ._ev_name
1041
- elif kind not in (3,):
1043
+ elif not _isin(kind, 3):
1042
1044
  raise GeoidError(kind=kind)
1043
1045
 
1044
1046
  self._egm = g = self._open(egm_pgm, datum, kind, _name__(**name), None)
@@ -1716,7 +1718,7 @@ def egmGeoidHeights(GeoidHeights_dat):
1716
1718
 
1717
1719
  __all__ += _ALL_DOCS(_GeoidBase)
1718
1720
 
1719
- if __name__ == '__main__': # MCCABE 14
1721
+ if __name__ == _DMAIN_: # MCCABE 14
1720
1722
 
1721
1723
  from pygeodesy.internals import printf, _secs2str, _versions, _sys
1722
1724
  from time import time
@@ -1727,30 +1729,31 @@ if __name__ == '__main__': # MCCABE 14
1727
1729
 
1728
1730
  geoids = _sys.argv[1:]
1729
1731
  while geoids:
1730
- geoid = geoids.pop(0)
1732
+ G = geoids.pop(0)
1733
+ g = G.lower()
1731
1734
 
1732
- if '-crop'.startswith(geoid.lower()):
1735
+ if '-crop'.startswith(g):
1733
1736
  _crop = dict(crp=(20, -125, 50, -65)) # CONUS
1734
1737
 
1735
- elif '-egm96'.startswith(geoid.lower()):
1738
+ elif '-egm96'.startswith(g):
1736
1739
  _GeoidEGM = GeoidEGM96
1737
1740
 
1738
- elif '-karney'.startswith(geoid.lower()):
1741
+ elif '-karney'.startswith(g):
1739
1742
  _GeoidEGM = GeoidKarney
1740
1743
 
1741
- elif '-kind'.startswith(geoid.lower()):
1744
+ elif '-kind'.startswith(g):
1742
1745
  _kind = int(geoids.pop(0))
1743
1746
 
1744
- elif '-pgm'.startswith(geoid.lower()):
1747
+ elif '-pgm'.startswith(g):
1745
1748
  _GeoidEGM = GeoidPGM
1746
1749
 
1747
- elif geoid[-4:].lower() in ('.pgm', '.grd'):
1748
- g = _GeoidEGM(geoid, kind=_kind, **_crop)
1750
+ elif _isin(g[-4:], '.pgm', '.grd'):
1751
+ g = _GeoidEGM(G, kind=_kind, **_crop)
1749
1752
  t = time()
1750
1753
  _ = g.highest()
1751
1754
  t = _secs2str(time() - t)
1752
1755
  printf('%s: %s (%s)', g.toStr(), t, _versions(), nl=1, nt=1)
1753
- t = g.pgm
1756
+ t = g.pgm
1754
1757
  if t:
1755
1758
  printf(repr(t), nt=1)
1756
1759
  # <https://GeographicLib.SourceForge.io/cgi-bin/GeoidEval>:
@@ -1771,12 +1774,12 @@ if __name__ == '__main__': # MCCABE 14
1771
1774
  except (GeoidError, RangeError) as x:
1772
1775
  printf(_COLONSPACE_(t, str(x)))
1773
1776
 
1774
- elif geoid[-4:].lower() in ('.bin',):
1775
- g = GeoidG2012B(geoid, kind=_kind)
1777
+ elif _isin(g[-4:], '.bin'):
1778
+ g = GeoidG2012B(G, kind=_kind)
1776
1779
  printf(g.toStr())
1777
1780
 
1778
1781
  else:
1779
- raise GeoidError(grid=repr(geoid))
1782
+ raise GeoidError(grid=repr(G))
1780
1783
 
1781
1784
  _I = int # PYCHOK unused _I
1782
1785
  del _intCs, _T, _T0s12 # trash ints cache and map
pygeodesy/hausdorff.py CHANGED
@@ -66,13 +66,14 @@ breaking} and C{random sampling} as in U{Abdel Aziz Taha, Allan Hanbury
66
66
  Analysis Machine Intelligence (PAMI), vol 37, no 11, pp 2153-2163, Nov 2015.
67
67
  '''
68
68
 
69
+ # from pygeodesy.basics import _isin # from .datums
69
70
  from pygeodesy.constants import INF, NINF, _0_0
70
- from pygeodesy.datums import _ellipsoidal_datum, _WGS84
71
+ from pygeodesy.datums import _ellipsoidal_datum, _WGS84, _isin
71
72
  from pygeodesy.errors import PointsError, _xattr, _xcallable, _xkwds, _xkwds_get
72
- import pygeodesy.formy as _formy
73
+ # from pygeodesy import formy as _formy # _MODS.into
73
74
  from pygeodesy.interns import NN, _i_, _j_, _units_
74
- # from pygeodesy.iters import points2 as _points # from .points
75
- from pygeodesy.lazily import _ALL_LAZY, _FOR_DOCS
75
+ # from pygeodesy.iters import points2 as _points2 # from .points
76
+ from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, _FOR_DOCS
76
77
  from pygeodesy.named import _name2__, _Named, _NamedTuple, _Pass
77
78
  # from pygeodesy.namedTuples import PhiLam2Tuple # from .points
78
79
  from pygeodesy.points import _distanceTo, PhiLam2Tuple, points2 as _points2, radians
@@ -84,7 +85,9 @@ from pygeodesy import unitsBase as _unitsBase # _Str_..., _xUnit, _xUnits
84
85
  from random import Random
85
86
 
86
87
  __all__ = _ALL_LAZY.hausdorff
87
- __version__ = '24.12.31'
88
+ __version__ = '25.04.21'
89
+
90
+ _formy = _MODS.into(formy=__name__)
88
91
 
89
92
 
90
93
  class HausdorffError(PointsError):
@@ -149,7 +152,7 @@ class Hausdorff(_Named):
149
152
  '''(INTERNAL) Set the datum.
150
153
  '''
151
154
  d = datum or _xattr(self._model[0], datum=datum)
152
- if d not in (None, self._datum): # PYCHOK no cover
155
+ if not _isin(d, None, self._datum): # PYCHOK no cover
153
156
  self._datum = _ellipsoidal_datum(d, name=self.name)
154
157
 
155
158
  def directed(self, point2s, early=True):
@@ -658,13 +661,13 @@ def _hausdorff_(ps1, ps2, both, early, seed, units, distance, point):
658
661
  # chance of an early break in the inner j loop
659
662
  rr = randomrangenerator(seed) if seed else range
660
663
 
661
- hd = NINF
662
- hi = hj = m = mn = 0
664
+ hd = NINF
665
+ mn = m = hi = hj = 0
663
666
  md = _0_0
664
667
 
665
668
  # forward or forward and backward
666
669
  for fb in range(2 if both else 1):
667
- n = len(ps2)
670
+ ji, n = False, len(ps2)
668
671
  for i in rr(len(ps1)):
669
672
  p1 = point(ps1[i])
670
673
  dh, dj = INF, 0
@@ -678,13 +681,14 @@ def _hausdorff_(ps1, ps2, both, early, seed, units, distance, point):
678
681
  else: # no early break
679
682
  if hd < dh:
680
683
  hd = dh
681
- if fb:
682
- hi, hj = dj, i
683
- else:
684
- hi, hj = i, dj
684
+ hi = i
685
+ hj = dj
686
+ ji = fb
685
687
  md += dh
686
688
  mn += 1
687
689
  m += 1
690
+ if ji: # swap indices
691
+ hi, hj = hj, hi
688
692
  # swap model and target
689
693
  ps1, ps2 = ps2, ps1
690
694
 
pygeodesy/heights.py CHANGED
@@ -77,9 +77,7 @@ from pygeodesy.datums import _ellipsoidal_datum, _WGS84
77
77
  from pygeodesy.errors import _AssertionError, LenError, PointsError, \
78
78
  _SciPyIssue, _xattr, _xkwds, _xkwds_get, _xkwds_item2
79
79
  # from pygeodesy.fmath import fidw # _MODS
80
- # from pygeodesy.formy import cosineLaw, cosineLawAL, cosineLawFAL, equirectangular4, \
81
- # euclidean, flatLocal, flatPolar, haversine, thomas, \
82
- # vincentys # _MODS.into
80
+ # from pygeodesy import formy as _formy # _MODS.into
83
81
  # from pygeodesy.internals import _version2 # _MODS
84
82
  from pygeodesy.interns import NN, _COMMASPACE_, _insufficient_, _NOTEQUAL_, \
85
83
  _PLUS_, _scipy_, _SPACE_, _STAR_
@@ -94,7 +92,7 @@ from pygeodesy.units import _isDegrees, Float_, Int_
94
92
  # from math import radians # from .points
95
93
 
96
94
  __all__ = _ALL_LAZY.heights
97
- __version__ = '24.12.31'
95
+ __version__ = '25.04.21'
98
96
 
99
97
  _error_ = 'error'
100
98
  _formy = _MODS.into(formy=__name__)
pygeodesy/internals.py CHANGED
@@ -5,9 +5,9 @@ u'''Mostly INTERNAL functions, except L{machine}, L{print_} and L{printf}.
5
5
  '''
6
6
  # from pygeodesy.basics import isiterablen, ubstr # _MODS
7
7
  # from pygeodesy.errors import _AttributeError, _error_init, _UnexpectedError, _xError2 # _MODS
8
- from pygeodesy.interns import NN, _BAR_, _COLON_, _DASH_, _DOT_, _ELLIPSIS_, _EQUALSPACED_, \
9
- _immutable_, _NL_, _pygeodesy_, _PyPy__, _python_, _QUOTE1_, \
10
- _QUOTE2_, _s_, _SPACE_, _sys, _UNDER_
8
+ from pygeodesy.interns import _BAR_, _COLON_, _DASH_, _DMAIN_, _DOT_, _ELLIPSIS_, _EQUALSPACED_, \
9
+ _immutable_, _NL_, NN, _pygeodesy_, _PyPy__, _python_, _QUOTE1_, \
10
+ _QUOTE2_, _s_, _SPACE_, _sys, _UNDER_
11
11
  from pygeodesy.interns import _COMMA_, _Python_ # PYCHOK used!
12
12
  # from pygeodesy.streprs import anstr, pairs, unstr # _MODS
13
13
 
@@ -24,26 +24,20 @@ _SIsecs = 'fs', 'ps', 'ns', 'us', 'ms', 'sec' # reversed
24
24
  _Windows_ = 'Windows'
25
25
 
26
26
 
27
- def _DUNDER_nameof(inst, *dflt):
28
- '''(INTERNAL) Get the DUNDER C{.__name__} attr.
27
+ def typename(obj, *dflt):
28
+ '''Get the C{obj.__name__}, the C{dflt} or its outer C{type.__name__} or C{NN} (C{str}).
29
29
  '''
30
30
  try:
31
- return inst.__name__
32
- except AttributeError:
31
+ return obj.__name__
32
+ except (AttributeError, ImportError): # LazyImportError
33
33
  pass
34
- return dflt[0] if dflt else inst.__class__.__name__
35
-
36
-
37
- def _DUNDER_nameof_(*names__): # in .errors._IsnotError
38
- '''(INTERNAL) Yield the _DUNDER_nameof or name.
39
- '''
40
- return map(_DUNDER_nameof, names__, names__)
34
+ return dflt[0] if dflt else typename(type(obj), NN)
41
35
 
42
36
 
43
37
  def _Property_RO(method):
44
38
  '''(INTERNAL) Can't import L{props.Property_RO}, I{recursively}.
45
39
  '''
46
- name = _DUNDER_nameof(method)
40
+ name = typename(method)
47
41
 
48
42
  def _del(inst, *unused): # PYCHOK no cover
49
43
  inst.__dict__.pop(name, None)
@@ -138,7 +132,7 @@ class _MODS_Base(object):
138
132
  def name(self):
139
133
  '''Get this name (C{str}).
140
134
  '''
141
- return _DUNDER_nameof(self.__class__)
135
+ return typename(self.__class__)
142
136
 
143
137
  @_Property_RO
144
138
  def nix2(self): # PYCHOK no cover
@@ -286,6 +280,12 @@ def _enquote(strs, quote=_QUOTE2_, white=NN): # in .basics, .solveBase
286
280
  return strs
287
281
 
288
282
 
283
+ def _envPYGEODESY(which, dflt=NN):
284
+ '''(INTERNAL) Return an C{PYGEODESY_...} ENV value or C{dflt}.
285
+ '''
286
+ return _getenv(_PYGEODESY_ENV(which), dflt)
287
+
288
+
289
289
  def _fper(p, q, per=_100_0, prec=1):
290
290
  '''Format a percentage C{B{p} * B{per} / B{q}} (C{str}).
291
291
  '''
@@ -295,12 +295,6 @@ def _fper(p, q, per=_100_0, prec=1):
295
295
  _getenv = _MODS.os.getenv # PYCHOK in .lazily, ...
296
296
 
297
297
 
298
- def _getPYGEODESY(which, dflt=NN):
299
- '''(INTERNAL) Return an C{PYGEODESY_...} ENV value or C{dflt}.
300
- '''
301
- return _getenv(_PYGEODESY(which), dflt)
302
-
303
-
304
298
  def _headof(name):
305
299
  '''(INTERNAL) Get the head name of qualified C{name} or the C{name}.
306
300
  '''
@@ -320,12 +314,6 @@ def _isAppleSi(): # PYCHOK no cover
320
314
  return _ismacOS() and machine().startswith(_arm64_)
321
315
 
322
316
 
323
- def _is_DUNDER_main(name):
324
- '''(INTERNAL) Return C{bool(name == '__main__')}.
325
- '''
326
- return name == '__main__'
327
-
328
-
329
317
  def _isiOS(): # in test/bases
330
318
  '''(INTERNAL) Is this C{iOS}? (C{bool})
331
319
  '''
@@ -350,7 +338,7 @@ def _isPyChOK(): # PYCHOK no cover
350
338
  '''
351
339
  # .../pychecker/checker.py --limit 0 --stdlib pygeodesy/<mod>/<name>.py
352
340
  return _sys.argv[0].endswith('/pychecker/checker.py') or \
353
- bool(_getPYGEODESY('PYCHOK'))
341
+ bool(_envPYGEODESY('PYCHOK'))
354
342
 
355
343
 
356
344
  def _isPyPy(): # in test/bases
@@ -407,9 +395,9 @@ def machine():
407
395
 
408
396
 
409
397
  def _name_version(pkg):
410
- '''(INTERNAL) Return C{pskg.__name__ + ' ' + .__version__}.
398
+ '''(INTERNAL) Return C{pkg.__name__ + ' ' + .__version__}.
411
399
  '''
412
- return _SPACE_(pkg.__name__, pkg.__version__)
400
+ return _SPACE_(typename(pkg), pkg.__version__) # _DVERSION_
413
401
 
414
402
 
415
403
  def _osversion2(sep=NN): # in .lazily, test/bases.versions
@@ -510,14 +498,10 @@ def _print7(nl=0, nt=0, prec=6, prefix=NN, sep=_SPACE_, file=_sys.stdout,
510
498
  return prefix, end, file, flush, prec, sep, kwds
511
499
 
512
500
 
513
- def _PYGEODESY(which, i=0):
501
+ def _PYGEODESY_ENV(which):
514
502
  '''(INTERNAL) Return an ENV C{str} C{PYGEODESY_...}.
515
503
  '''
516
- try:
517
- w = which.__name__.lstrip(_UNDER_)[i:]
518
- except AttributeError:
519
- w = which
520
- return _UNDER_(_pygeodesy_, w).upper()
504
+ return _UNDER_(_pygeodesy_, typename(which, which)).upper()
521
505
 
522
506
 
523
507
  def _Pythonarchine(sep=NN): # in .lazily, test/bases versions
@@ -613,7 +597,7 @@ def _tailof(name):
613
597
  return name[i:] if i > 0 else name
614
598
 
615
599
 
616
- def _under(name): # PYCHOK in .datums, .auxilats, .ups, .utm, .utmupsBase, ...
600
+ def _under(name): # PYCHOK in .datums, .auxilats, .geodesicw, .ups, .utm, .utmupsBase, ...
617
601
  '''(INTERNAL) Prefix C{name} with an I{underscore}.
618
602
  '''
619
603
  return name if name.startswith(_UNDER_) else NN(_UNDER_, name)
@@ -643,7 +627,7 @@ def _usage(file_py, *args, **opts_help): # in .etm, .geodesici # PYCHOK no cov
643
627
 
644
628
  args = _help(**opts_help) or (tuple(_opts(**opts_help)) + args)
645
629
 
646
- u = _COLON_(_DUNDER_nameof(_usage)[1:], NN)
630
+ u = _COLON_(typename(_usage)[1:], NN)
647
631
  return _SPACE_(u, *_usage_argv(file_py, *args))
648
632
 
649
633
 
@@ -656,7 +640,7 @@ def _usage_argv(argv0, *args):
656
640
  .replace(o.sep, _DOT_).strip()
657
641
  b = o.path.basename(argv0)
658
642
  b, x = o.path.splitext(b)
659
- if x == '.py' and not _is_DUNDER_main(b):
643
+ if x == '.py' and b != _DMAIN_:
660
644
  m = _DOT_(m or _pygeodesy_, b)
661
645
  p = NN(_python_, _MODS.sys_version_info2[0])
662
646
  return (p, '-m', _enquote(m)) + args
@@ -701,10 +685,10 @@ def _versions(sep=_SPACE_):
701
685
  return sep.join(l7) if sep else l7 # 5- or 6-list
702
686
 
703
687
 
704
- __all__ = tuple(map(_DUNDER_nameof, (machine, print_, printf)))
705
- __version__ = '25.04.04'
688
+ __all__ = tuple(map(typename, (machine, print_, printf, typename)))
689
+ __version__ = '25.04.14'
706
690
 
707
- if _is_DUNDER_main(__name__): # PYCHOK no cover
691
+ if __name__ == _DMAIN_:
708
692
 
709
693
  def _main():
710
694
  from pygeodesy import _isfrozen, isLazy
@@ -715,7 +699,7 @@ if _is_DUNDER_main(__name__): # PYCHOK no cover
715
699
  _main()
716
700
 
717
701
  # % python3 -m pygeodesy.internals
718
- # pygeodesy 25.4.4 Python 3.13.2 64bit arm64 macOS 15.4 _isfrozen False isLazy 1
702
+ # pygeodesy 25.4.14 Python 3.13.2 64bit arm64 macOS 15.4 _isfrozen False isLazy 1
719
703
 
720
704
  # **) MIT License
721
705
  #
pygeodesy/interns.py CHANGED
@@ -117,13 +117,15 @@ class _Slicer(str):
117
117
  class MISSING(object):
118
118
  '''(INTERNAL) Singleton C{str}.
119
119
  '''
120
+ def __init__(self):
121
+ self.__name__ = type(self).__name__
122
+
120
123
  def toRepr(self, **unused):
121
- return self.__class__.__name__
124
+ return type(self).__name__
122
125
 
123
126
  __repr__ = __str__ = toStr = toRepr
124
127
 
125
- MISSING = MISSING() # PYCHOK singleton
126
- MISSING.__name__ = str(MISSING)
128
+ MISSING = MISSING() # PYCHOK singleton
127
129
 
128
130
  # __DUNDER__-style names would get mangled in classes
129
131
  _0_ = '0' # PYCHOK 'zero'
@@ -186,6 +188,7 @@ _conversion_ = 'conversion' # PYCHOK OK
186
188
  _convex_ = 'convex' # PYCHOK OK
187
189
  _d_ = 'd' # PYCHOK OK
188
190
  _D_ = 'D' # PYCHOK OK
191
+ _DALL_ = '__all__' # PYCHOK _DUNDER_(NN, 'all', NN)
189
192
  _DASH_ = Str_('-') # PYCHOK == _MINUS_
190
193
  _datum_ = 'datum' # PYCHOK OK
191
194
  _decode3_ = 'decode3' # PYCHOK OK
@@ -197,10 +200,10 @@ _DEPRECATED_ = 'DEPRECATED' # PYCHOK OK
197
200
  _DEQUALSPACED_ = Str_(' == ') # PYCHOK OK
198
201
  _distance_ = 'distance' # PYCHOK OK
199
202
  _distant_ = _Prefix('distant') # PYCHOK OK
203
+ _DMAIN_ = '__main__' # PYCHOK _DUNDER_(NN, 'main', NN)
204
+ _DNAME_ = '__name__' # PYCHOK _DUNDER_(NN, _name_, NN)
200
205
  _doesn_t_exist_ = "doesn't exist" # PYCHOK OK
201
206
  _DOT_ = Str_('.') # PYCHOK OK
202
- _DUNDER_all_ = '__all__' # PYCHOK OK
203
- _DUNDER_name_ = '__name__' # PYCHOK _DUNDER_(NN, _name_, NN)
204
207
  _duplicate_ = 'duplicate' # PYCHOK OK
205
208
  _e_ = 'e' # PYCHOK OK
206
209
  _E_ = 'E' # PYCHOK OK
@@ -440,9 +443,9 @@ _LR_PAIRS = {_LANGLE_: _RANGLE_,
440
443
 
441
444
  __all__ = (_NN_, # NOT MISSING!
442
445
  Str_.__name__) # classes
443
- __version__ = '25.01.12'
446
+ __version__ = '25.04.12'
444
447
 
445
- if __name__ == '__main__':
448
+ if __name__ == _DMAIN_:
446
449
 
447
450
  def _main():
448
451
  from pygeodesy import itemsorted, printf
pygeodesy/iters.py CHANGED
@@ -9,12 +9,12 @@ the initial items, skipping of duplicate items and copying of the
9
9
  iterated items.
10
10
  '''
11
11
 
12
- from pygeodesy.basics import islistuple, issubclassof, len2, \
13
- map2, _passarg
12
+ from pygeodesy.basics import _isin, islistuple, issubclassof, \
13
+ len2, map2, _passarg, typename
14
14
  # from pygeodesy.constants import _1_0 # from .utily
15
15
  from pygeodesy.errors import _IndexError, LenError, PointsError, \
16
16
  _TypeError, _ValueError
17
- # from pygeodesy.internals import _passarg # from .basics
17
+ # from pygeodesy.internals import _passarg, typename # from .basics
18
18
  from pygeodesy.interns import _0_, _composite_, _few_, _latlon_, \
19
19
  _points_, _too_
20
20
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS
@@ -26,7 +26,7 @@ from pygeodesy.units import Int, Radius
26
26
  from pygeodesy.utily import degrees2m, _Wrap, _1_0
27
27
 
28
28
  __all__ = _ALL_LAZY.iters
29
- __version__ = '24.06.09'
29
+ __version__ = '25.04.14'
30
30
 
31
31
  _items_ = 'items'
32
32
  _iterNumpy2len = 1 # adjustable for testing purposes
@@ -382,7 +382,7 @@ class LatLon2PsxyIter(PointsIter):
382
382
 
383
383
  @raise TypeError: Some B{C{points}} are not B{C{base}}-compatible.
384
384
  '''
385
- if self._deg2m not in (None, _1_0):
385
+ if not _isin(self._deg2m, None, _1_0):
386
386
  _p3 = self._point3Tuple
387
387
  else:
388
388
  def _p3(ll): # PYCHOK redef
@@ -417,7 +417,7 @@ def isNumpy2(obj):
417
417
  instance, C{False} otherwise.
418
418
  '''
419
419
  # isinstance(self, (Numpy2LatLon, ...))
420
- return getattr(obj, isNumpy2.__name__, False)
420
+ return getattr(obj, typename(isNumpy2), False)
421
421
 
422
422
 
423
423
  def isPoints2(obj):
@@ -429,7 +429,7 @@ def isPoints2(obj):
429
429
  instance, C{False} otherwise.
430
430
  '''
431
431
  # isinstance(self, (LatLon2psxy, ...))
432
- return getattr(obj, isPoints2.__name__, False)
432
+ return getattr(obj, typename(isPoints2), False)
433
433
 
434
434
 
435
435
  def isTuple2(obj):
@@ -441,7 +441,7 @@ def isTuple2(obj):
441
441
  instance, C{False} otherwise.
442
442
  '''
443
443
  # isinstance(self, (Tuple2LatLon, ...))
444
- return getattr(obj, isTuple2.__name__, False)
444
+ return getattr(obj, typename(isTuple2), False)
445
445
 
446
446
 
447
447
  def iterNumpy2(obj):