pygeodesy 24.10.24__py2.py3-none-any.whl → 24.12.12__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 (118) hide show
  1. {PyGeodesy-24.10.24.dist-info → PyGeodesy-24.12.12.dist-info}/METADATA +6 -6
  2. PyGeodesy-24.12.12.dist-info/RECORD +118 -0
  3. {PyGeodesy-24.10.24.dist-info → PyGeodesy-24.12.12.dist-info}/WHEEL +1 -1
  4. pygeodesy/__init__.py +5 -5
  5. pygeodesy/__main__.py +1 -1
  6. pygeodesy/albers.py +5 -5
  7. pygeodesy/auxilats/_CX_4.py +1 -1
  8. pygeodesy/auxilats/_CX_6.py +1 -1
  9. pygeodesy/auxilats/_CX_8.py +1 -1
  10. pygeodesy/auxilats/_CX_Rs.py +1 -1
  11. pygeodesy/auxilats/__init__.py +1 -1
  12. pygeodesy/auxilats/__main__.py +1 -1
  13. pygeodesy/auxilats/auxAngle.py +5 -5
  14. pygeodesy/auxilats/auxDLat.py +6 -6
  15. pygeodesy/auxilats/auxDST.py +2 -2
  16. pygeodesy/auxilats/auxLat.py +5 -5
  17. pygeodesy/auxilats/auxily.py +2 -2
  18. pygeodesy/azimuthal.py +55 -65
  19. pygeodesy/basics.py +35 -34
  20. pygeodesy/booleans.py +37 -37
  21. pygeodesy/cartesianBase.py +26 -65
  22. pygeodesy/clipy.py +1 -1
  23. pygeodesy/constants.py +7 -7
  24. pygeodesy/css.py +8 -9
  25. pygeodesy/datums.py +1 -1
  26. pygeodesy/deprecated/__init__.py +2 -2
  27. pygeodesy/deprecated/bases.py +1 -1
  28. pygeodesy/deprecated/classes.py +10 -10
  29. pygeodesy/deprecated/consterns.py +1 -1
  30. pygeodesy/deprecated/datum.py +1 -1
  31. pygeodesy/deprecated/functions.py +23 -13
  32. pygeodesy/deprecated/nvector.py +1 -1
  33. pygeodesy/deprecated/rhumbBase.py +1 -1
  34. pygeodesy/deprecated/rhumbaux.py +1 -1
  35. pygeodesy/deprecated/rhumbsolve.py +1 -1
  36. pygeodesy/deprecated/rhumbx.py +1 -1
  37. pygeodesy/dms.py +1 -1
  38. pygeodesy/ecef.py +63 -69
  39. pygeodesy/elevations.py +1 -1
  40. pygeodesy/ellipsoidalBase.py +106 -121
  41. pygeodesy/ellipsoidalBaseDI.py +115 -119
  42. pygeodesy/ellipsoidalExact.py +36 -38
  43. pygeodesy/ellipsoidalGeodSolve.py +1 -1
  44. pygeodesy/ellipsoidalKarney.py +1 -1
  45. pygeodesy/ellipsoidalNvector.py +1 -1
  46. pygeodesy/ellipsoidalVincenty.py +6 -5
  47. pygeodesy/ellipsoids.py +7 -8
  48. pygeodesy/elliptic.py +6 -6
  49. pygeodesy/epsg.py +1 -1
  50. pygeodesy/errors.py +25 -25
  51. pygeodesy/etm.py +84 -76
  52. pygeodesy/fmath.py +54 -51
  53. pygeodesy/formy.py +74 -106
  54. pygeodesy/frechet.py +1 -1
  55. pygeodesy/fstats.py +1 -1
  56. pygeodesy/fsums.py +82 -72
  57. pygeodesy/gars.py +1 -1
  58. pygeodesy/geodesici.py +4 -4
  59. pygeodesy/geodesicw.py +16 -15
  60. pygeodesy/geodesicx/_C4_24.py +2 -2
  61. pygeodesy/geodesicx/_C4_27.py +2 -2
  62. pygeodesy/geodesicx/_C4_30.py +2 -2
  63. pygeodesy/geodesicx/__init__.py +3 -3
  64. pygeodesy/geodesicx/__main__.py +1 -1
  65. pygeodesy/geodesicx/gx.py +6 -5
  66. pygeodesy/geodesicx/gxarea.py +2 -2
  67. pygeodesy/geodesicx/gxbases.py +2 -2
  68. pygeodesy/geodesicx/gxline.py +16 -12
  69. pygeodesy/geodsolve.py +8 -17
  70. pygeodesy/geohash.py +1 -1
  71. pygeodesy/geoids.py +6 -6
  72. pygeodesy/hausdorff.py +1 -1
  73. pygeodesy/heights.py +3 -3
  74. pygeodesy/internals.py +64 -80
  75. pygeodesy/interns.py +2 -3
  76. pygeodesy/iters.py +1 -1
  77. pygeodesy/karney.py +4 -4
  78. pygeodesy/ktm.py +20 -21
  79. pygeodesy/latlonBase.py +296 -346
  80. pygeodesy/lazily.py +15 -15
  81. pygeodesy/lcc.py +5 -5
  82. pygeodesy/ltp.py +55 -59
  83. pygeodesy/ltpTuples.py +208 -192
  84. pygeodesy/mgrs.py +9 -10
  85. pygeodesy/named.py +153 -3
  86. pygeodesy/namedTuples.py +58 -7
  87. pygeodesy/nvectorBase.py +122 -105
  88. pygeodesy/osgr.py +10 -13
  89. pygeodesy/points.py +1 -1
  90. pygeodesy/props.py +3 -3
  91. pygeodesy/resections.py +26 -26
  92. pygeodesy/rhumb/__init__.py +2 -2
  93. pygeodesy/rhumb/aux_.py +2 -2
  94. pygeodesy/rhumb/bases.py +2 -2
  95. pygeodesy/rhumb/ekx.py +4 -4
  96. pygeodesy/rhumb/solve.py +4 -4
  97. pygeodesy/simplify.py +291 -403
  98. pygeodesy/solveBase.py +1 -1
  99. pygeodesy/sphericalBase.py +1 -1
  100. pygeodesy/sphericalNvector.py +84 -127
  101. pygeodesy/sphericalTrigonometry.py +66 -71
  102. pygeodesy/streprs.py +10 -5
  103. pygeodesy/trf.py +1 -1
  104. pygeodesy/triaxials.py +23 -16
  105. pygeodesy/units.py +17 -17
  106. pygeodesy/unitsBase.py +1 -1
  107. pygeodesy/ups.py +4 -4
  108. pygeodesy/utily.py +202 -145
  109. pygeodesy/utm.py +10 -10
  110. pygeodesy/utmups.py +1 -1
  111. pygeodesy/utmupsBase.py +1 -1
  112. pygeodesy/vector2d.py +17 -17
  113. pygeodesy/vector3d.py +32 -23
  114. pygeodesy/vector3dBase.py +22 -19
  115. pygeodesy/webmercator.py +5 -5
  116. pygeodesy/wgrs.py +5 -5
  117. PyGeodesy-24.10.24.dist-info/RECORD +0 -118
  118. {PyGeodesy-24.10.24.dist-info → PyGeodesy-24.12.12.dist-info}/top_level.txt +0 -0
@@ -49,14 +49,13 @@ from pygeodesy.lazily import _ALL_DOCS, _ALL_MODS as _MODS
49
49
  from pygeodesy.karney import _around, _atan2d, Caps, GDict, _fix90, \
50
50
  _K_2_0, _llz2gl, _norm2, _norm180, \
51
51
  _sincos2, _sincos2d
52
- from pygeodesy.named import Property_RO, _update_all
53
- # from pygeodesy.props import Property_RO, _update_all # from .named
54
- from pygeodesy.utily import atan2d as _atan2d_reverse, sincos2
52
+ from pygeodesy.props import Property_RO, property_ROver, _update_all
53
+ from pygeodesy.utily import atan2, atan2d as _atan2d_reverse, sincos2
55
54
 
56
- from math import atan2, cos, degrees, fabs, floor, radians, sin
55
+ from math import cos, degrees, fabs, floor, radians, sin
57
56
 
58
57
  __all__ = ()
59
- __version__ = '24.07.12'
58
+ __version__ = '24.11.24'
60
59
 
61
60
  _glXs = [] # instances of C{[_]GeodesicLineExact} to be updated
62
61
 
@@ -377,11 +376,11 @@ class _GeodesicLineExact(_GeodesicBase):
377
376
  lam12 = salp0 * self._H0e2_f1 * fsum1f_(eF.deltaH(ssig2, csig2, dn2),
378
377
  -self._H1, sig12)
379
378
  if (outmask & Cs.LONG_UNROLL):
380
- _a, t = atan2, _copysign_1_0(salp0) # east-going?
379
+ t = _copysign_1_0(salp0) # east-going?
381
380
  tchi1 = t * schi1
382
381
  tchi2 = t * schi2
383
- chi12 = t * fsum1f_(_a(ssig1, csig1), -_a(ssig2, csig2),
384
- _a(tchi2, cchi2), -_a(tchi1, cchi1), sig12)
382
+ chi12 = t * fsum1f_(atan2(ssig1, csig1), -atan2(ssig2, csig2),
383
+ atan2(tchi2, cchi2), -atan2(tchi1, cchi1), sig12)
385
384
  lon2 = self.lon1 + degrees(chi12 - lam12)
386
385
  else:
387
386
  chi12 = atan2(*_sincos12(schi1, cchi1, schi2, cchi2))
@@ -634,6 +633,13 @@ class _GeodesicLineExact(_GeodesicBase):
634
633
  # unnecessary because Einv inverts E
635
634
  # return -self._eF.deltaEinv(stau1, ctau1)
636
635
 
636
+ @property_ROver
637
+ def _toProps7(self):
638
+ '''(INTERNAL) 7-Tuple of C{toStr} properties.
639
+ '''
640
+ C = _GeodesicLineExact
641
+ return C.lat1, C.lon1, C.azi1, C.a13, C.s13, C.caps, C.geodesic
642
+
637
643
  def toStr(self, **prec_sep_name): # PYCHOK signature
638
644
  '''Return this C{GeodesicLineExact} as string.
639
645
 
@@ -642,16 +648,14 @@ class _GeodesicLineExact(_GeodesicBase):
642
648
 
643
649
  @return: C{GeodesicLineExact} (C{str}).
644
650
  '''
645
- C = _GeodesicLineExact
646
- t = C.lat1, C.lon1, C.azi1, C.a13, C.s13, C.caps, C.geodesic
647
- return self._instr(props=t, **prec_sep_name)
651
+ return self._instr(props=self._toProps7, **prec_sep_name)
648
652
 
649
653
 
650
654
  __all__ += _ALL_DOCS(_GeodesicLineExact)
651
655
 
652
656
  # **) MIT License
653
657
  #
654
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
658
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
655
659
  #
656
660
  # Permission is hereby granted, free of charge, to any person obtaining a
657
661
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/geodsolve.py CHANGED
@@ -23,7 +23,7 @@ from pygeodesy.solveBase import _SolveGDictBase, _SolveGDictLineBase
23
23
  from pygeodesy.utily import _unrollon, _Wrap, wrap360
24
24
 
25
25
  __all__ = _ALL_LAZY.geodsolve
26
- __version__ = '24.10.14'
26
+ __version__ = '24.11.02'
27
27
 
28
28
 
29
29
  class _GeodesicSolveBase(_SolveGDictBase):
@@ -181,15 +181,6 @@ class GeodesicSolve(_GeodesicSolveBase):
181
181
  ll2 = _unrollon(ll1, _Wrap.point(ll2))
182
182
  return self.InverseLine(ll1.lat, ll1.lon, ll2.lat, ll2.lon, **caps_name)
183
183
 
184
- # def _InverseLine2(self, lat1, lon1, lat2, lon2, **caps_name): # in .geodesici
185
- # '''(INTERNAL) Helper for L{InverseLine} and L{_InverseLine}.
186
- # '''
187
- # r = self.Inverse(lat1, lon1, lat2, lon2)
188
- # gl = GeodesicLineSolve(self, lat1, lon1, r.azi1, **_name1__(caps_name, _or_nameof=self))
189
- # gl._a13 = r.a12 # gl.SetArc(r.a12)
190
- # gl._s13 = r.s12 # gl.SetDistance(r.s12)
191
- # return gl, r
192
-
193
184
  def InverseLine(self, lat1, lon1, lat2, lon2, **caps_name): # PYCHOK no cover
194
185
  '''Set up a L{GeodesicLineSolve} to compute several points
195
186
  on a single geodesic.
@@ -270,14 +261,14 @@ class GeodesicLineSolve(_GeodesicSolveBase, _SolveGDictLineBase):
270
261
  '''
271
262
  return self._a13
272
263
 
273
- def Arc(self):
264
+ def Arc(self): # PYCHOK no cover
274
265
  '''Return the arc length to reference point 3 (C{degrees} or C{NAN}).
275
266
 
276
267
  @see: Method L{SetArc} and property L{a13}.
277
268
  '''
278
269
  return self.a13
279
270
 
280
- def ArcPosition(self, a12, outmask=Caps.STANDARD): # PYCHOK unused
271
+ def ArcPosition(self, a12, outmask=Caps.STANDARD): # PYCHOK no cover
281
272
  '''Find the position on the line given B{C{a12}}.
282
273
 
283
274
  @arg a12: Spherical arc length from the first point to the
@@ -347,7 +338,7 @@ class GeodesicLineSolve(_GeodesicSolveBase, _SolveGDictLineBase):
347
338
  '''
348
339
  return self._s13
349
340
 
350
- def SetArc(self, a13):
341
+ def SetArc(self, a13): # PYCHOK no cover
351
342
  '''Set reference point 3 in terms relative to the first point.
352
343
 
353
344
  @arg a13: Spherical arc length from the first to the reference
@@ -362,13 +353,13 @@ class GeodesicLineSolve(_GeodesicSolveBase, _SolveGDictLineBase):
362
353
  # _update_all(self)
363
354
  return self._s13
364
355
 
365
- def SetDistance(self, s13):
356
+ def SetDistance(self, s13): # PYCHOK no cover
366
357
  '''Set reference point 3 in terms relative to the first point.
367
358
 
368
359
  @arg s13: Distance from the first to the reference point (C{meter}).
369
360
 
370
- @return: The arc length C{a13} (C{degrees}) between the first
371
- and the reference point or C{NAN}.
361
+ @return: The arc length C{a13} (C{degrees}) between the first and
362
+ the reference point or C{NAN}.
372
363
  '''
373
364
  if self._s13 != s13:
374
365
  self._s13 = s13
@@ -513,7 +504,7 @@ if __name__ == '__main__':
513
504
 
514
505
  # **) MIT License
515
506
  #
516
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
507
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
517
508
  #
518
509
  # Permission is hereby granted, free of charge, to any person obtaining a
519
510
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/geohash.py CHANGED
@@ -1099,7 +1099,7 @@ if __name__ == '__main__':
1099
1099
 
1100
1100
  # **) MIT License
1101
1101
  #
1102
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
1102
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
1103
1103
  #
1104
1104
  # Permission is hereby granted, free of charge, to any person obtaining a
1105
1105
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/geoids.py CHANGED
@@ -15,7 +15,7 @@ The L{GeoidG2012B} and L{GeoidPGM} interpolators both depend on U{scipy
15
15
  require those packages to be installed.
16
16
 
17
17
  In addition, each geoid interpolator needs C{grid knots} (down)loaded from
18
- a C{geoid} model file, I{specific to the interpolator}, more details below
18
+ a C{geoid} model file, I{specific to the interpolator}. More details below
19
19
  and in the documentation of the interpolator class. For each interpolator,
20
20
  there are several interpolation choices, like I{linear}, I{cubic}, etc.
21
21
 
@@ -42,7 +42,7 @@ C{>>> h = ginterpolator(ll)}
42
42
 
43
43
  or
44
44
 
45
- C{>>> h0, h1, h2, ... = ginterpolator(ll0, ll1, ll2, ...)}
45
+ C{>>> h1, h2, h3, ... = ginterpolator(ll1, ll2, ll3, ...)}
46
46
 
47
47
  or a list, tuple, generator, etc. of C{LatLon}s
48
48
 
@@ -118,7 +118,7 @@ except ImportError: # Python 3+
118
118
  from io import BytesIO as _BytesIO # PYCHOK expected
119
119
 
120
120
  __all__ = _ALL_LAZY.geoids
121
- __version__ = '24.10.11'
121
+ __version__ = '24.11.05'
122
122
 
123
123
  _assert_ = 'assert'
124
124
  _bHASH_ = b'#'
@@ -159,7 +159,7 @@ class _GeoidBase(_HeightBase):
159
159
  _smooth = 0 # used only for RectBivariateSpline
160
160
  _stdev = None # fixed in GeoidKarney
161
161
  _u2B = 0 # np.itemsize or undefined
162
- _yx_hits = None # cache hits, ala Karney
162
+ _yx_hits = None # cache hits, ala Karney's
163
163
 
164
164
  # _lat_d = _0_0 # increment, +tive
165
165
  # _lat_lo = _0_0 # lower lat, south
@@ -1621,7 +1621,7 @@ class _PGM(_Gpars):
1621
1621
 
1622
1622
 
1623
1623
  class PGMError(GeoidError):
1624
- '''Issue parsing or cropping an C{egm*.pgm} geoid dataset.
1624
+ '''An issue while parsing or cropping an C{egm*.pgm} geoid dataset.
1625
1625
  '''
1626
1626
  pass
1627
1627
 
@@ -1837,7 +1837,7 @@ del _intCs # trash ints cache
1837
1837
 
1838
1838
  # **) MIT License
1839
1839
  #
1840
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
1840
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
1841
1841
  #
1842
1842
  # Permission is hereby granted, free of charge, to any person obtaining a
1843
1843
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/hausdorff.py CHANGED
@@ -882,7 +882,7 @@ def randomrangenerator(seed):
882
882
 
883
883
  # **) MIT License
884
884
  #
885
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
885
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
886
886
  #
887
887
  # Permission is hereby granted, free of charge, to any person obtaining a
888
888
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/heights.py CHANGED
@@ -91,7 +91,7 @@ from pygeodesy.units import _isDegrees, Float_, Int_
91
91
  # from math import radians # from .points
92
92
 
93
93
  __all__ = _ALL_LAZY.heights
94
- __version__ = '24.08.24'
94
+ __version__ = '24.11.02'
95
95
 
96
96
  _error_ = 'error'
97
97
  _formy = _MODS.into(formy=__name__)
@@ -1031,7 +1031,7 @@ class HeightIDWkarney(_HeightIDW):
1031
1031
  <https://WikiPedia.org/wiki/Inverse_distance_weighting>} (IDW) and the
1032
1032
  I{angular} distance in C{degrees} from I{Karney}'s U{geographiclib
1033
1033
  <https://PyPI.org/project/geographiclib>} method U{Geodesic.Inverse
1034
- <https://geographiclib.sourceforge.io/Python/doc/code.html#
1034
+ <https://GeographicLib.SourceForge.io/Python/doc/code.html#
1035
1035
  geographiclib.geodesic.Geodesic.Inverse>}.
1036
1036
  '''
1037
1037
  def __init__(self, knots, beta=2, datum=None, **name__wrap):
@@ -1110,7 +1110,7 @@ __all__ += _ALL_DOCS(_HeightBase, _HeightIDW, _HeightNamed)
1110
1110
 
1111
1111
  # **) MIT License
1112
1112
  #
1113
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
1113
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
1114
1114
  #
1115
1115
  # Permission is hereby granted, free of charge, to any person obtaining a
1116
1116
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/internals.py CHANGED
@@ -7,7 +7,7 @@ u'''Mostly INTERNAL functions, except L{machine}, L{print_} and L{printf}.
7
7
  # from pygeodesy.errors import _AttributeError, _error_init, _UnexpectedError, _xError2 # _MODS
8
8
  from pygeodesy.interns import NN, _BAR_, _COLON_, _DASH_, _DOT_, _ELLIPSIS_, _EQUALSPACED_, \
9
9
  _immutable_, _NL_, _pygeodesy_, _PyPy__, _python_, _QUOTE1_, \
10
- _QUOTE2_, _s_, _SPACE_, _sys, _UNDER_, _utf_8_
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
 
@@ -16,6 +16,7 @@ from pygeodesy.interns import _COMMA_, _Python_ # PYCHOK used!
16
16
  # import sys as _sys # from .interns
17
17
 
18
18
  _0_0 = 0.0 # PYCHOK in .basics, .constants
19
+ _100_0 = 100.0 # in .constants
19
20
  _arm64_ = 'arm64'
20
21
  _iOS_ = 'iOS'
21
22
  _macOS_ = 'macOS'
@@ -40,14 +41,14 @@ def _DUNDER_nameof_(*names__): # in .errors._IsnotError
40
41
 
41
42
 
42
43
  def _Property_RO(method):
43
- '''(INTERNAL) Can't I{recursively} import L{props.property_RO}.
44
+ '''(INTERNAL) Can't import L{props.Property_RO}, I{recursively}.
44
45
  '''
45
46
  name = _DUNDER_nameof(method)
46
47
 
47
- def _del(inst, attr): # PYCHOK no cover
48
- delattr(inst, attr) # force error
48
+ def _del(inst, *unused): # PYCHOK no cover
49
+ inst.__dict__.pop(name, None)
49
50
 
50
- def _get(inst, **unused): # PYCHOK 2 vs 3 args
51
+ def _get(inst, *unused): # PYCHOK 2 vs 3 args
51
52
  try: # to get the cached value immediately
52
53
  v = inst.__dict__[name]
53
54
  except (AttributeError, KeyError):
@@ -69,7 +70,8 @@ class _MODS_Base(object):
69
70
 
70
71
  def __setattr__(self, attr, value): # PYCHOK no cover
71
72
  e = _MODS.errors
72
- t = _EQUALSPACED_(self._DOT_(attr), repr(value))
73
+ n = _DOT_(self.name, attr)
74
+ t = _EQUALSPACED_(n, repr(value))
73
75
  raise e._AttributeError(_immutable_, txt=t)
74
76
 
75
77
  @_Property_RO
@@ -84,7 +86,6 @@ class _MODS_Base(object):
84
86
  '''Get platform 2-list C{[bits, machine]}, I{once}.
85
87
  '''
86
88
  import platform as p
87
-
88
89
  m = p.machine() # ARM64, arm64, x86_64, iPhone13,2, etc.
89
90
  m = m.replace(_COMMA_, _UNDER_)
90
91
  if m.lower() == 'x86_64': # PYCHOK on Intel or Rosetta2 ...
@@ -99,30 +100,15 @@ class _MODS_Base(object):
99
100
 
100
101
  @_Property_RO
101
102
  def ctypes3(self):
102
- '''Get 3-tuple C{(ctypes.CDLL, ._dlopen, .util.findlibrary)}, I{once}.
103
+ '''Get C{ctypes.CDLL}, C{find_library} and C{dlopen}, I{once}.
103
104
  '''
104
- if _ismacOS():
105
- from ctypes import CDLL, DEFAULT_MODE, _dlopen
106
-
107
- def dlopen(name):
108
- return _dlopen(name, DEFAULT_MODE)
109
-
110
- else: # PYCHOK no cover
111
- from ctypes import CDLL
112
- dlopen = _passarg
113
-
114
- from ctypes.util import find_library
115
- return CDLL, dlopen, find_library
105
+ import ctypes as c
106
+ from ctypes.util import find_library as f
116
107
 
117
- @_Property_RO
118
- def ctypes5(self):
119
- '''Get 5-tuple C{(ctypes.byref, .c_char_p, .c_size_t, .c_uint, .sizeof)}, I{once}.
120
- '''
121
- from ctypes import byref, c_char_p, c_size_t, c_uint, sizeof # get_errno
122
- return byref, c_char_p, c_size_t, c_uint, sizeof
108
+ def dlopen(name): # on macOS only
109
+ return c._dlopen(name, c.DEFAULT_MODE)
123
110
 
124
- def _DOT_(self, name): # PYCHOK no cover
125
- return _DOT_(self.name, name)
111
+ return c.CDLL, f, (dlopen if _ismacOS() else None)
126
112
 
127
113
  @_Property_RO
128
114
  def errors(self):
@@ -143,15 +129,10 @@ class _MODS_Base(object):
143
129
  '''
144
130
  try: # Pythonista only
145
131
  from platform import iOS_ver
146
- return iOS_ver()
132
+ t = iOS_ver()
147
133
  except (AttributeError, ImportError):
148
- return NN, (NN, NN, NN), NN
149
-
150
- @_Property_RO
151
- def libc(self):
152
- '''Load C{libc.dll|dylib}, I{once}.
153
- '''
154
- return _load_lib('libc')
134
+ t = NN, (NN, NN, NN), NN
135
+ return t
155
136
 
156
137
  @_Property_RO
157
138
  def name(self):
@@ -161,13 +142,12 @@ class _MODS_Base(object):
161
142
 
162
143
  @_Property_RO
163
144
  def nix2(self): # PYCHOK no cover
164
- '''Get Linux 2-list C{[distro, version]}, I{once}.
145
+ '''Get Linux 2-tuple C{(distro, version)}, I{once}.
165
146
  '''
166
- import platform as p
167
-
168
- n, v = p.uname()[0], NN
147
+ from platform import uname
148
+ v, n = NN, uname()[0] # [0] == .system
169
149
  if n.lower() == 'linux':
170
- try: # use distro only for Linux, not macOS, etc.
150
+ try: # use distro only on Linux, not macOS, etc.
171
151
  import distro # <https://PyPI.org/project/distro>
172
152
  _a = _MODS.streprs.anstr
173
153
  v = _a(distro.version()) # first
@@ -197,7 +177,6 @@ class _MODS_Base(object):
197
177
  '''Get 2-list C{[OS, release]}, I{once}.
198
178
  '''
199
179
  import platform as p
200
-
201
180
  _Nix, _ = _MODS.nix2
202
181
  # - mac_ver() returns ('10.12.5', ..., 'x86_64') on
203
182
  # macOS and ('10.3.3', ..., 'iPad4,2') on iOS
@@ -217,26 +196,26 @@ class _MODS_Base(object):
217
196
  if v and n:
218
197
  break
219
198
  else:
220
- n = v = NN # XXX AssertioError?
199
+ n = v = NN # XXX AssertionError?
221
200
  return [n, v]
222
201
 
223
202
  @_Property_RO
224
203
  def _Popen_kwds2(self):
225
204
  '''(INTERNAL) Get C{subprocess.Popen} and C{-kwds}.
226
205
  '''
227
- import subprocess as _sub
206
+ import subprocess as s
228
207
  kwds = dict(creationflags=0, # executable=sys.executable, shell=True,
229
- stdin=_sub.PIPE, stdout=_sub.PIPE, stderr=_sub.STDOUT)
230
- if _sys.version_info[:2] > (3, 6):
208
+ stdin=s.PIPE, stdout=s.PIPE, stderr=s.STDOUT)
209
+ if _MODS.sys_version_info2 > (3, 6):
231
210
  kwds.update(text=True)
232
- return _sub.Popen, kwds
211
+ return s.Popen, kwds
233
212
 
234
213
  @_Property_RO
235
214
  def Pythonarchine(self):
236
215
  '''Get 3- or 4-list C{[PyPy, Python, bits, machine]}, I{once}.
237
216
  '''
238
217
  v = _sys.version
239
- l3 = [_Python_(v)] + self.bits_machine2
218
+ l3 = [_Python_(v)] + _MODS.bits_machine2
240
219
  pypy = _PyPy__(v)
241
220
  if pypy: # PYCHOK no cover
242
221
  l3.insert(0, pypy)
@@ -270,23 +249,23 @@ def _caller3(up, base=True): # in .lazily, .named
270
249
  for the caller B{C{up}} frames back in the Python call stack.
271
250
 
272
251
  @kwarg base: Use C{B{base}=False} for the fully-qualified file
273
- name, otherwise the base (module) name (C{bool}).
252
+ name, otherwise the base (module) name (C{bool}).
274
253
  '''
275
254
  f = None
276
- _f = _MODS.os.path.basename if base else _passarg
255
+ _b = _MODS.os.path.basename if base else _passarg
277
256
  try:
278
257
  f = _sys._getframe(up + 1) # == inspect.stack()[up + 1][0]
279
258
  t = _MODS.inspect.getframeinfo(f)
280
- t = t.function, _f(t.filename), t.lineno
259
+ t = t.function, _b(t.filename), t.lineno
281
260
  # or ...
282
261
  # f = _sys._getframe(up + 1)
283
262
  # c = f.f_code
284
263
  # t = (c.co_name, # caller name
285
- # _f(c.co_filename), # file name .py
264
+ # _b(c.co_filename), # file name .py
286
265
  # f.f_lineno) # line number
287
266
  # or ...
288
267
  # t = _MODS.inspect.stack()[up + 1] # (frame, filename, lineno, function, ...)
289
- # t = t[3], _f(t[1]), t[2]
268
+ # t = t[3], _b(t[1]), t[2]
290
269
  except (AttributeError, IndexError, ValueError):
291
270
  # sys._getframe(1) ... 'importlib._bootstrap' line 1032,
292
271
  # may throw a ValueError('call stack not deep enough')
@@ -307,7 +286,7 @@ def _enquote(strs, quote=_QUOTE2_, white=NN): # in .basics, .solveBase
307
286
  return strs
308
287
 
309
288
 
310
- def _fper(p, q, per=100.0, prec=1):
289
+ def _fper(p, q, per=_100_0, prec=1):
311
290
  '''Format a percentage C{B{p} * B{per} / B{q}} (C{str}).
312
291
  '''
313
292
  return '%.*f%%' % (prec, (float(p) * per / float(q)))
@@ -335,7 +314,7 @@ def _headof(name):
335
314
  # return (a == b) if _isPyPy() else (a is b)
336
315
 
337
316
 
338
- def _isAppleSi():
317
+ def _isAppleSi(): # PYCHOK no cover
339
318
  '''(INTERNAL) Is this C{macOS on Apple Silicon}? (C{bool})
340
319
  '''
341
320
  return _ismacOS() and machine().startswith(_arm64_)
@@ -366,7 +345,7 @@ def _isNix(): # in test/bases
366
345
  return _MODS.nix2[0]
367
346
 
368
347
 
369
- def _isPyChecker():
348
+ def _isPyChecker(): # PYCHOK no cover
370
349
  '''(INTERNAL) Is C{PyChecker} running? (C{bool}).
371
350
  '''
372
351
  # .../pychecker/checker.py --limit 0 --stdlib pygeodesy/<mod>/<name>.py
@@ -390,17 +369,19 @@ def _isWindows(): # in test/bases
390
369
  def _load_lib(name):
391
370
  '''(INTERNAL) Load a C{dylib}, B{C{name}} must startwith('lib').
392
371
  '''
393
- # macOS 11+ (aka 10.16) no longer provides direct loading of
394
- # system libraries. As a result, C{ctypes.util.find_library}
395
- # will not find any library, unless previously installed by a
396
- # low-level dlopen(name) call (with the library base C{name}).
397
- CDLL, dlopen, find_lib = _MODS.ctypes3
398
-
372
+ CDLL, find_lib, dlopen = _MODS.ctypes3
399
373
  ns = find_lib(name), name
400
- if dlopen is not _passarg: # _ismacOS()
374
+ if dlopen:
375
+ # macOS 11+ (aka 10.16) no longer provides direct loading of
376
+ # system libraries. As a result, C{ctypes.util.find_library}
377
+ # will not find any library, unless previously installed by a
378
+ # low-level dlopen(name) call (with the library base C{name}).
401
379
  ns += (_DOT_(name, 'dylib'),
402
380
  _DOT_(name, 'framework'), _MODS.os.path.join(
403
381
  _DOT_(name, 'framework'), name))
382
+ else: # not macOS
383
+ dlopen = _passarg # no-op
384
+
404
385
  for n in ns:
405
386
  try:
406
387
  if n and dlopen(n): # pre-load handle
@@ -548,7 +529,7 @@ def _Pythonarchine(sep=NN): # in .lazily, test/bases versions
548
529
  def _secs2str(secs): # in .geoids, ../test/bases
549
530
  '''Convert a time in C{secs} to C{str}.
550
531
  '''
551
- if secs < 100.0: # _100_0
532
+ if secs < _100_0:
552
533
  unit = len(_SIsecs) - 1
553
534
  while 0 < secs < 1 and unit > 0:
554
535
  secs *= 1e3 # _1000_0
@@ -610,18 +591,18 @@ def _sizeof(obj, deep=True):
610
591
 
611
592
 
612
593
  def _sysctl_uint(name):
613
- '''(INTERNAL) Get an unsigned int sysctl item by name, use on macOS ONLY!
594
+ '''(INTERNAL) Get an C{unsigned int sysctl} item by name, I{ONLY on macOS!}
614
595
  '''
615
- libc = _MODS.libc
596
+ libc = _load_lib('libc') if _ismacOS() else None
616
597
  if libc: # <https://StackOverflow.com/questions/759892/python-ctypes-and-sysctl>
617
- byref, char_p, size_t, uint, sizeof = _MODS.ctypes5
618
- n = name if str is bytes else bytes(name, _utf_8_) # PYCHOK isPython2 = str is bytes
619
- u = uint(0)
620
- z = size_t(sizeof(u))
621
- r = libc.sysctlbyname(char_p(n), byref(u), byref(z), None, size_t(0))
622
- else: # couldn't find or load 'libc'
598
+ import ctypes as c
599
+ n = c.c_char_p(_MODS.basics.str2ub(name)) # bytes(name, _utf_8_)
600
+ u = c.c_uint(0)
601
+ z = c.c_size_t(c.sizeof(u))
602
+ r = libc.sysctlbyname(n, c.byref(u), c.byref(z), None, c.c_size_t(0)) # PYCHOK attr
603
+ else: # not macOS or couldn't find or load 'libc'=
623
604
  r = -2
624
- return int(r if r else u.value) # -1 ENOENT error, -2 no libc
605
+ return int(r if r else u.value) # -1 ENOENT error, -2 no libc or not macOS
625
606
 
626
607
 
627
608
  def _tailof(name):
@@ -637,7 +618,7 @@ def _under(name): # PYCHOK in .datums, .auxilats, .ups, .utm, .utmupsBase, ...
637
618
  return name if name.startswith(_UNDER_) else NN(_UNDER_, name)
638
619
 
639
620
 
640
- def _usage(file_py, *args, **opts_help): # in .etm, .geodesici
621
+ def _usage(file_py, *args, **opts_help): # in .etm, .geodesici # PYCHOK no cover
641
622
  '''(INTERNAL) Build "usage: python -m ..." cmd line for module B{C{file_py}}.
642
623
  '''
643
624
  if opts_help:
@@ -671,12 +652,12 @@ def _usage_argv(argv0, *args):
671
652
  o = _MODS.os
672
653
  m = o.path.dirname(argv0)
673
654
  m = m.replace(o.getcwd(), _ELLIPSIS_) \
674
- .replace(o.sep, _DOT_).strip()
655
+ .replace(o.sep, _DOT_).strip()
675
656
  b = o.path.basename(argv0)
676
657
  b, x = o.path.splitext(b)
677
658
  if x == '.py' and not _is_DUNDER_main(b):
678
659
  m = _DOT_(m or _pygeodesy_, b)
679
- p = NN(_python_, _sys.version_info[0])
660
+ p = NN(_python_, _MODS.sys_version_info2[0])
680
661
  return (p, '-m', _enquote(m)) + args
681
662
 
682
663
 
@@ -689,7 +670,7 @@ def _version2(version, n=2):
689
670
  return t[:n]
690
671
 
691
672
 
692
- def _version_info(package): # in .Base.karney, .basics
673
+ def _version_info(package): # in .basics, .karney._kWrapped.Math
693
674
  '''(INTERNAL) Get the C{package.__version_info__} as a 2- or
694
675
  3-tuple C{(major, minor, revision)} if C{int}s.
695
676
  '''
@@ -713,14 +694,14 @@ def _version_ints(vs):
713
694
 
714
695
 
715
696
  def _versions(sep=_SPACE_):
716
- '''(INTERNAL) Get pygeodesy, PyPy and Python versions, bits, machine and OS as C{7- or 8-list} or C{str}.
697
+ '''(INTERNAL) Get pygeodesy, PyPy and Python versions, bits, machine and OS as C{8- or 9-list} or C{str}.
717
698
  '''
718
699
  l7 = [_pygeodesy_, _MODS.version] + _Pythonarchine() + _osversion2()
719
700
  return sep.join(l7) if sep else l7 # 5- or 6-list
720
701
 
721
702
 
722
703
  __all__ = tuple(map(_DUNDER_nameof, (machine, print_, printf)))
723
- __version__ = '24.10.20'
704
+ __version__ = '24.11.06'
724
705
 
725
706
  if _is_DUNDER_main(__name__): # PYCHOK no cover
726
707
 
@@ -732,9 +713,12 @@ if _is_DUNDER_main(__name__): # PYCHOK no cover
732
713
 
733
714
  _main()
734
715
 
716
+ # % python3 -m pygeodesy.internals
717
+ # pygeodesy 24.11.11 Python 3.13.0 64bit arm64 macOS 14.6.1 _isfrozen False isLazy 1
718
+
735
719
  # **) MIT License
736
720
  #
737
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
721
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
738
722
  #
739
723
  # Permission is hereby granted, free of charge, to any person obtaining a
740
724
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/interns.py CHANGED
@@ -217,7 +217,6 @@ _ellipsoidal_ = 'ellipsoidal' # PYCHOK OK
217
217
  _encode_ = 'encode' # PYCHOK OK
218
218
  _end_ = 'end' # PYCHOK OK
219
219
  _epoch_ = 'epoch' # PYCHOK OK
220
- _eps_ = 'eps' # PYCHOK OK
221
220
  _EQUAL_ = Str_('=') # PYCHOK OK
222
221
  _EQUALSPACED_ = Str_(' = ') # PYCHOK OK
223
222
  _Error_ = 'Error' # PYCHOK OK
@@ -441,7 +440,7 @@ _LR_PAIRS = {_LANGLE_: _RANGLE_,
441
440
 
442
441
  __all__ = (_NN_, # NOT MISSING!
443
442
  Str_.__name__) # classes
444
- __version__ = '24.10.19'
443
+ __version__ = '24.11.27'
445
444
 
446
445
  if __name__ == '__main__':
447
446
 
@@ -464,7 +463,7 @@ if __name__ == '__main__':
464
463
 
465
464
  # **) MIT License
466
465
  #
467
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
466
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
468
467
  #
469
468
  # Permission is hereby granted, free of charge, to any person obtaining a
470
469
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/iters.py CHANGED
@@ -527,7 +527,7 @@ __all__ += _ALL_DOCS(_BaseIter)
527
527
 
528
528
  # **) MIT License
529
529
  #
530
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
530
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
531
531
  #
532
532
  # Permission is hereby granted, free of charge, to any person obtaining a
533
533
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/karney.py CHANGED
@@ -64,7 +64,7 @@ Karney-based functionality
64
64
  <https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1Intersect.html>} from I{GeographicLib 2.3+}
65
65
 
66
66
  - L{JacobiConformal} -- U{JacobiConformal
67
- <https://geographiclib.sourceforge.io/C++/doc/classGeographicLib_1_1experimental_1_1JacobiConformal.html>}
67
+ <https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1experimental_1_1JacobiConformal.html>}
68
68
 
69
69
  - L{KTransverseMercator} - U{TransverseMercator
70
70
  <https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1TransverseMercator.html>}
@@ -165,7 +165,7 @@ from pygeodesy.utily import atan2d, sincos2d, tand, _unrollon, fabs
165
165
  # from math import fabs # from .utily
166
166
 
167
167
  __all__ = _ALL_LAZY.karney
168
- __version__ = '24.10.14'
168
+ __version__ = '24.11.26'
169
169
 
170
170
  _2_4_ = '2.4'
171
171
  _K_2_0 = _getenv(_PYGEODESY(_xgeographiclib, 1), _2_)
@@ -1011,7 +1011,7 @@ def _tand(x):
1011
1011
  try:
1012
1012
  return _wrapped.Math.tand(x)
1013
1013
  except AttributeError:
1014
- return tand(x)
1014
+ return tand(x) # Error=None
1015
1015
 
1016
1016
 
1017
1017
  def _unroll2(lon1, lon2, wrap=False): # see .ellipsoidalBaseDI._intersects2
@@ -1039,7 +1039,7 @@ __all__ += _ALL_DOCS(_CapsBase)
1039
1039
 
1040
1040
  # **) MIT License
1041
1041
  #
1042
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
1042
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
1043
1043
  #
1044
1044
  # Permission is hereby granted, free of charge, to any person obtaining a
1045
1045
  # copy of this software and associated documentation files (the "Software"),