pygeodesy 25.1.9__py2.py3-none-any.whl → 25.4.25__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 (96) hide show
  1. pygeodesy/__init__.py +35 -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 +59 -40
  8. pygeodesy/auxilats/__init__.py +3 -3
  9. pygeodesy/auxilats/__main__.py +9 -7
  10. pygeodesy/auxilats/auxAngle.py +2 -2
  11. pygeodesy/auxilats/auxLat.py +13 -13
  12. pygeodesy/auxilats/auxily.py +13 -9
  13. pygeodesy/azimuthal.py +7 -6
  14. pygeodesy/basics.py +65 -22
  15. pygeodesy/booleans.py +12 -10
  16. pygeodesy/cartesianBase.py +21 -20
  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 +10 -7
  26. pygeodesy/elevations.py +9 -8
  27. pygeodesy/ellipsoidalBase.py +19 -8
  28. pygeodesy/ellipsoidalBaseDI.py +17 -15
  29. pygeodesy/ellipsoidalNvector.py +6 -3
  30. pygeodesy/ellipsoidalVincenty.py +4 -1
  31. pygeodesy/ellipsoids.py +167 -138
  32. pygeodesy/elliptic.py +9 -9
  33. pygeodesy/errors.py +44 -43
  34. pygeodesy/etm.py +9 -9
  35. pygeodesy/fmath.py +10 -9
  36. pygeodesy/formy.py +11 -12
  37. pygeodesy/frechet.py +216 -109
  38. pygeodesy/fstats.py +5 -4
  39. pygeodesy/fsums.py +107 -122
  40. pygeodesy/gars.py +7 -7
  41. pygeodesy/geodesici.py +15 -14
  42. pygeodesy/geodesicw.py +34 -32
  43. pygeodesy/geodesicx/__init__.py +1 -1
  44. pygeodesy/geodesicx/__main__.py +12 -10
  45. pygeodesy/geodesicx/gx.py +30 -33
  46. pygeodesy/geodesicx/gxarea.py +2 -2
  47. pygeodesy/geodesicx/gxline.py +5 -5
  48. pygeodesy/geodsolve.py +18 -17
  49. pygeodesy/geohash.py +7 -8
  50. pygeodesy/geoids.py +35 -34
  51. pygeodesy/hausdorff.py +17 -13
  52. pygeodesy/heights.py +2 -4
  53. pygeodesy/internals.py +31 -46
  54. pygeodesy/interns.py +12 -9
  55. pygeodesy/iters.py +8 -8
  56. pygeodesy/karney.py +73 -66
  57. pygeodesy/ktm.py +5 -5
  58. pygeodesy/latlonBase.py +14 -18
  59. pygeodesy/lazily.py +73 -74
  60. pygeodesy/lcc.py +11 -9
  61. pygeodesy/ltp.py +8 -7
  62. pygeodesy/ltpTuples.py +2 -2
  63. pygeodesy/mgrs.py +7 -6
  64. pygeodesy/named.py +47 -31
  65. pygeodesy/nvectorBase.py +7 -7
  66. pygeodesy/osgr.py +9 -8
  67. pygeodesy/points.py +12 -10
  68. pygeodesy/props.py +25 -25
  69. pygeodesy/resections.py +11 -10
  70. pygeodesy/rhumb/__init__.py +1 -1
  71. pygeodesy/rhumb/aux_.py +14 -14
  72. pygeodesy/rhumb/bases.py +22 -20
  73. pygeodesy/rhumb/ekx.py +6 -6
  74. pygeodesy/rhumb/solve.py +15 -15
  75. pygeodesy/solveBase.py +3 -3
  76. pygeodesy/sphericalBase.py +6 -6
  77. pygeodesy/sphericalNvector.py +6 -5
  78. pygeodesy/sphericalTrigonometry.py +8 -7
  79. pygeodesy/streprs.py +14 -14
  80. pygeodesy/trf.py +14 -12
  81. pygeodesy/triaxials.py +29 -26
  82. pygeodesy/units.py +5 -4
  83. pygeodesy/unitsBase.py +5 -4
  84. pygeodesy/ups.py +3 -3
  85. pygeodesy/utily.py +4 -4
  86. pygeodesy/utmups.py +4 -4
  87. pygeodesy/utmupsBase.py +88 -18
  88. pygeodesy/vector2d.py +18 -11
  89. pygeodesy/vector3d.py +7 -6
  90. pygeodesy/webmercator.py +6 -5
  91. pygeodesy/wgrs.py +6 -5
  92. {pygeodesy-25.1.9.dist-info → pygeodesy-25.4.25.dist-info}/METADATA +35 -31
  93. pygeodesy-25.4.25.dist-info/RECORD +118 -0
  94. pygeodesy-25.1.9.dist-info/RECORD +0 -118
  95. {pygeodesy-25.1.9.dist-info → pygeodesy-25.4.25.dist-info}/WHEEL +0 -0
  96. {pygeodesy-25.1.9.dist-info → pygeodesy-25.4.25.dist-info}/top_level.txt +0 -0
pygeodesy/geohash.py CHANGED
@@ -17,14 +17,13 @@ U{Geohashes<https://www.Movable-Type.co.UK/scripts/geohash.html>}.
17
17
  U{geohash-js<https://GitHub.com/DaveTroy/geohash-js>}.
18
18
  '''
19
19
 
20
- from pygeodesy.basics import isstr, map2
20
+ from pygeodesy.basics import isstr, map2, _splituple
21
21
  from pygeodesy.constants import EPS, R_M, _0_0, _0_5, _180_0, _360_0, \
22
22
  _90_0, _N_90_0, _N_180_0 # PYCHOK used!
23
23
  from pygeodesy.errors import _ValueError, _xkwds, _xStrError
24
- # from pygeodesy import formy as _formy # _MODS
25
- from pygeodesy.interns import NN, _COMMA_, _DOT_, _E_, _height_, _N_, _NE_, \
26
- _NW_, _radius_, _S_, _SE_, _SPACE_, _SW_, _W_, \
27
- _width_ # _INV_
24
+ # from pygeodesy import formy as _formy # _MODS.into
25
+ from pygeodesy.interns import NN, _DMAIN_, _DOT_, _E_, _height_, _N_, _NE_, \
26
+ _NW_, _radius_, _S_, _SE_, _SW_, _W_, _width_ # _INV_
28
27
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS
29
28
  from pygeodesy.named import _name__, _NamedDict, _NamedTuple, nameof, _xnamed
30
29
  from pygeodesy.namedTuples import Bounds2Tuple, Bounds4Tuple, LatLon2Tuple, \
@@ -38,7 +37,7 @@ from pygeodesy.units import Degrees_, Int, Lat_, Lon_, Meter, Precision_, Str
38
37
  from math import fabs, ldexp, log10, radians
39
38
 
40
39
  __all__ = _ALL_LAZY.geohash
41
- __version__ = '24.10.12'
40
+ __version__ = '25.04.21'
42
41
 
43
42
  _formy = _MODS.into(formy=__name__)
44
43
  _MASK5 = 16, 8, 4, 2, 1 # PYCHOK used!
@@ -290,7 +289,7 @@ class Geohash(Str):
290
289
  if isinstance(lat_ghll, Geohash):
291
290
  gh, ll = str(lat_ghll), lat_ghll.latlon
292
291
  elif isstr(lat_ghll): # "lat, lon" or "geohash"
293
- ll = lat_ghll.replace(_COMMA_, _SPACE_).split()
292
+ ll = _splituple(lat_ghll)
294
293
  if len(ll) > 1:
295
294
  gh, ll = _GH.encode2(ll[0], ll[1], precision, eps)
296
295
  else:
@@ -1070,7 +1069,7 @@ __all__ += _ALL_DOCS(bounds, # functions
1070
1069
  neighbors, precision, resolution2, sizes3, vincentys_,
1071
1070
  decode_error, sizes) # DEPRECATED
1072
1071
 
1073
- if __name__ == '__main__':
1072
+ if __name__ == _DMAIN_:
1074
1073
 
1075
1074
  from pygeodesy.internals import printf, _versions
1076
1075
  from timeit import timeit
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, 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,12 +101,11 @@ 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
- from pygeodesy.interns import _COMMA_ # PYCHOK used!
109
109
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS, _FOR_DOCS
110
110
  from pygeodesy.named import _name__, _Named, _NamedTuple
111
111
  # from pygeodesy.namedTuples import LatLon3Tuple # _MODS
@@ -126,7 +126,7 @@ except ImportError: # Python 3+
126
126
  from io import BytesIO as _BytesIO # PYCHOK expected
127
127
 
128
128
  __all__ = _ALL_LAZY.geoids
129
- __version__ = '24.12.31'
129
+ __version__ = '25.04.14'
130
130
 
131
131
  _assert_ = 'assert'
132
132
  _bHASH_ = b'#'
@@ -572,7 +572,7 @@ class _GeoidBase(_HeightBase):
572
572
  except (IOError, OSError) as x:
573
573
  raise GeoidError(geoid=geoid, cause=x)
574
574
 
575
- if datum not in (None, self._datum):
575
+ if not _isin(datum, None, self._datum):
576
576
  self._datum = _ellipsoidal_datum(datum, name=name)
577
577
  self._kind = int(kind)
578
578
  if name:
@@ -652,15 +652,16 @@ class _GeoidBase(_HeightBase):
652
652
 
653
653
  @return: Geoid name and attributes (C{str}).
654
654
  '''
655
- s = 1 if self.kind < 0 else 2
656
- t = tuple(Fmt.PAREN(m.__name__, fstr(m(), prec=prec)) for m in
657
- (self.lowerleft, self.upperright,
658
- self.center,
659
- self.highest, self.lowest)) + \
660
- attrs( _mean_, _stdev_, prec=prec, Nones=False) + \
661
- attrs((_kind_, 'smooth')[:s], prec=prec, Nones=False) + \
662
- attrs( 'cropped', 'dtype', _endian_, 'hits', 'knots', 'nBytes',
663
- '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)
664
665
  return _COLONSPACE_(self, sep.join(t))
665
666
 
666
667
  @Property_RO
@@ -912,8 +913,7 @@ def _I(i):
912
913
  def _T(cs):
913
914
  '''(INTERNAL) Cache a tuple of single C{int} constants.
914
915
  '''
915
- cs = cs.replace(_COMMA_, _SPACE_).strip()
916
- return tuple(map(_I, cs.split()))
916
+ return tuple(map(_I, _splituple(cs)))
917
917
 
918
918
  _T0s12 = (_I(0),) * 12 # PYCHOK _T('0, 0, ..., 0')
919
919
 
@@ -1038,9 +1038,9 @@ class GeoidKarney(_GeoidBase):
1038
1038
  if smooth is not None:
1039
1039
  raise GeoidError(smooth=smooth, txt_not_=_supported_)
1040
1040
 
1041
- if kind in (2,):
1041
+ if _isin(kind, 2):
1042
1042
  self._ev2d = self._ev2k # see ._ev_name
1043
- elif kind not in (3,):
1043
+ elif not _isin(kind, 3):
1044
1044
  raise GeoidError(kind=kind)
1045
1045
 
1046
1046
  self._egm = g = self._open(egm_pgm, datum, kind, _name__(**name), None)
@@ -1718,7 +1718,7 @@ def egmGeoidHeights(GeoidHeights_dat):
1718
1718
 
1719
1719
  __all__ += _ALL_DOCS(_GeoidBase)
1720
1720
 
1721
- if __name__ == '__main__': # MCCABE 14
1721
+ if __name__ == _DMAIN_: # MCCABE 14
1722
1722
 
1723
1723
  from pygeodesy.internals import printf, _secs2str, _versions, _sys
1724
1724
  from time import time
@@ -1729,30 +1729,31 @@ if __name__ == '__main__': # MCCABE 14
1729
1729
 
1730
1730
  geoids = _sys.argv[1:]
1731
1731
  while geoids:
1732
- geoid = geoids.pop(0)
1732
+ G = geoids.pop(0)
1733
+ g = G.lower()
1733
1734
 
1734
- if '-crop'.startswith(geoid.lower()):
1735
+ if '-crop'.startswith(g):
1735
1736
  _crop = dict(crp=(20, -125, 50, -65)) # CONUS
1736
1737
 
1737
- elif '-egm96'.startswith(geoid.lower()):
1738
+ elif '-egm96'.startswith(g):
1738
1739
  _GeoidEGM = GeoidEGM96
1739
1740
 
1740
- elif '-karney'.startswith(geoid.lower()):
1741
+ elif '-karney'.startswith(g):
1741
1742
  _GeoidEGM = GeoidKarney
1742
1743
 
1743
- elif '-kind'.startswith(geoid.lower()):
1744
+ elif '-kind'.startswith(g):
1744
1745
  _kind = int(geoids.pop(0))
1745
1746
 
1746
- elif '-pgm'.startswith(geoid.lower()):
1747
+ elif '-pgm'.startswith(g):
1747
1748
  _GeoidEGM = GeoidPGM
1748
1749
 
1749
- elif geoid[-4:].lower() in ('.pgm', '.grd'):
1750
- g = _GeoidEGM(geoid, kind=_kind, **_crop)
1750
+ elif _isin(g[-4:], '.pgm', '.grd'):
1751
+ g = _GeoidEGM(G, kind=_kind, **_crop)
1751
1752
  t = time()
1752
1753
  _ = g.highest()
1753
1754
  t = _secs2str(time() - t)
1754
1755
  printf('%s: %s (%s)', g.toStr(), t, _versions(), nl=1, nt=1)
1755
- t = g.pgm
1756
+ t = g.pgm
1756
1757
  if t:
1757
1758
  printf(repr(t), nt=1)
1758
1759
  # <https://GeographicLib.SourceForge.io/cgi-bin/GeoidEval>:
@@ -1773,12 +1774,12 @@ if __name__ == '__main__': # MCCABE 14
1773
1774
  except (GeoidError, RangeError) as x:
1774
1775
  printf(_COLONSPACE_(t, str(x)))
1775
1776
 
1776
- elif geoid[-4:].lower() in ('.bin',):
1777
- g = GeoidG2012B(geoid, kind=_kind)
1777
+ elif _isin(g[-4:], '.bin'):
1778
+ g = GeoidG2012B(G, kind=_kind)
1778
1779
  printf(g.toStr())
1779
1780
 
1780
1781
  else:
1781
- raise GeoidError(grid=repr(geoid))
1782
+ raise GeoidError(grid=repr(G))
1782
1783
 
1783
1784
  _I = int # PYCHOK unused _I
1784
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
  '''
@@ -345,11 +333,12 @@ def _isNix(): # in test/bases
345
333
  return _MODS.nix2[0]
346
334
 
347
335
 
348
- def _isPyChecker(): # PYCHOK no cover
349
- '''(INTERNAL) Is C{PyChecker} running? (C{bool}).
336
+ def _isPyChOK(): # PYCHOK no cover
337
+ '''(INTERNAL) Is C{PyChecker} running? (C{bool})
350
338
  '''
351
339
  # .../pychecker/checker.py --limit 0 --stdlib pygeodesy/<mod>/<name>.py
352
- return _sys.argv[0].endswith('/pychecker/checker.py')
340
+ return _sys.argv[0].endswith('/pychecker/checker.py') or \
341
+ bool(_envPYGEODESY('PYCHOK'))
353
342
 
354
343
 
355
344
  def _isPyPy(): # in test/bases
@@ -406,9 +395,9 @@ def machine():
406
395
 
407
396
 
408
397
  def _name_version(pkg):
409
- '''(INTERNAL) Return C{pskg.__name__ + ' ' + .__version__}.
398
+ '''(INTERNAL) Return C{pkg.__name__ + ' ' + .__version__}.
410
399
  '''
411
- return _SPACE_(pkg.__name__, pkg.__version__)
400
+ return _SPACE_(typename(pkg), pkg.__version__) # _DVERSION_
412
401
 
413
402
 
414
403
  def _osversion2(sep=NN): # in .lazily, test/bases.versions
@@ -509,14 +498,10 @@ def _print7(nl=0, nt=0, prec=6, prefix=NN, sep=_SPACE_, file=_sys.stdout,
509
498
  return prefix, end, file, flush, prec, sep, kwds
510
499
 
511
500
 
512
- def _PYGEODESY(which, i=0):
501
+ def _PYGEODESY_ENV(which):
513
502
  '''(INTERNAL) Return an ENV C{str} C{PYGEODESY_...}.
514
503
  '''
515
- try:
516
- w = which.__name__.lstrip(_UNDER_)[i:]
517
- except AttributeError:
518
- w = which
519
- return _UNDER_(_pygeodesy_, w).upper()
504
+ return _UNDER_(_pygeodesy_, typename(which, which)).upper()
520
505
 
521
506
 
522
507
  def _Pythonarchine(sep=NN): # in .lazily, test/bases versions
@@ -612,7 +597,7 @@ def _tailof(name):
612
597
  return name[i:] if i > 0 else name
613
598
 
614
599
 
615
- def _under(name): # PYCHOK in .datums, .auxilats, .ups, .utm, .utmupsBase, ...
600
+ def _under(name): # PYCHOK in .datums, .auxilats, .geodesicw, .ups, .utm, .utmupsBase, ...
616
601
  '''(INTERNAL) Prefix C{name} with an I{underscore}.
617
602
  '''
618
603
  return name if name.startswith(_UNDER_) else NN(_UNDER_, name)
@@ -642,7 +627,7 @@ def _usage(file_py, *args, **opts_help): # in .etm, .geodesici # PYCHOK no cov
642
627
 
643
628
  args = _help(**opts_help) or (tuple(_opts(**opts_help)) + args)
644
629
 
645
- u = _COLON_(_DUNDER_nameof(_usage)[1:], NN)
630
+ u = _COLON_(typename(_usage)[1:], NN)
646
631
  return _SPACE_(u, *_usage_argv(file_py, *args))
647
632
 
648
633
 
@@ -655,7 +640,7 @@ def _usage_argv(argv0, *args):
655
640
  .replace(o.sep, _DOT_).strip()
656
641
  b = o.path.basename(argv0)
657
642
  b, x = o.path.splitext(b)
658
- if x == '.py' and not _is_DUNDER_main(b):
643
+ if x == '.py' and b != _DMAIN_:
659
644
  m = _DOT_(m or _pygeodesy_, b)
660
645
  p = NN(_python_, _MODS.sys_version_info2[0])
661
646
  return (p, '-m', _enquote(m)) + args
@@ -700,10 +685,10 @@ def _versions(sep=_SPACE_):
700
685
  return sep.join(l7) if sep else l7 # 5- or 6-list
701
686
 
702
687
 
703
- __all__ = tuple(map(_DUNDER_nameof, (machine, print_, printf)))
704
- __version__ = '24.11.06'
688
+ __all__ = tuple(map(typename, (machine, print_, printf, typename)))
689
+ __version__ = '25.04.14'
705
690
 
706
- if _is_DUNDER_main(__name__): # PYCHOK no cover
691
+ if __name__ == _DMAIN_:
707
692
 
708
693
  def _main():
709
694
  from pygeodesy import _isfrozen, isLazy
@@ -714,7 +699,7 @@ if _is_DUNDER_main(__name__): # PYCHOK no cover
714
699
  _main()
715
700
 
716
701
  # % python3 -m pygeodesy.internals
717
- # pygeodesy 24.11.11 Python 3.13.0 64bit arm64 macOS 14.6.1 _isfrozen False isLazy 1
702
+ # pygeodesy 25.4.14 Python 3.13.2 64bit arm64 macOS 15.4 _isfrozen False isLazy 1
718
703
 
719
704
  # **) MIT License
720
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
@@ -429,8 +432,8 @@ _SW_ = _S_ + _W_ # PYCHOK negative ones
429
432
  _DDOT_ = Str_(_DOT_ * 2) # PYCHOK OK
430
433
  # _DEQUAL_ = Str_(_EQUAL_ * 2) # PYCHOK OK
431
434
  # _DNL_ = Str_(_NL_ * 2) # PYCHOK OK
432
- # _DSLASH_ = Str_(_SLASH_ * 2) # PYCHOK OK
433
- # _DSTAR_ = Str_(_STAR_ * 2) # PYCHOK OK
435
+ _DSLASH_ = Str_(_SLASH_ * 2) # PYCHOK OK
436
+ _DSTAR_ = Str_(_STAR_ * 2) # PYCHOK OK
434
437
  _DUNDER_ = Str_(_UNDER_ * 2) # PYCHOK OK
435
438
 
436
439
  _LR_PAIRS = {_LANGLE_: _RANGLE_,
@@ -440,9 +443,9 @@ _LR_PAIRS = {_LANGLE_: _RANGLE_,
440
443
 
441
444
  __all__ = (_NN_, # NOT MISSING!
442
445
  Str_.__name__) # classes
443
- __version__ = '24.11.27'
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):