pygeodesy 24.3.24__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 (115) hide show
  1. PyGeodesy-24.3.24.dist-info/METADATA +272 -0
  2. PyGeodesy-24.3.24.dist-info/RECORD +115 -0
  3. PyGeodesy-24.3.24.dist-info/WHEEL +6 -0
  4. PyGeodesy-24.3.24.dist-info/top_level.txt +1 -0
  5. pygeodesy/LICENSE +21 -0
  6. pygeodesy/__init__.py +615 -0
  7. pygeodesy/__main__.py +103 -0
  8. pygeodesy/albers.py +867 -0
  9. pygeodesy/auxilats/_CX_4.py +218 -0
  10. pygeodesy/auxilats/_CX_6.py +314 -0
  11. pygeodesy/auxilats/_CX_8.py +475 -0
  12. pygeodesy/auxilats/__init__.py +54 -0
  13. pygeodesy/auxilats/__main__.py +86 -0
  14. pygeodesy/auxilats/auxAngle.py +548 -0
  15. pygeodesy/auxilats/auxDLat.py +302 -0
  16. pygeodesy/auxilats/auxDST.py +296 -0
  17. pygeodesy/auxilats/auxLat.py +848 -0
  18. pygeodesy/auxilats/auxily.py +272 -0
  19. pygeodesy/azimuthal.py +1150 -0
  20. pygeodesy/basics.py +892 -0
  21. pygeodesy/booleans.py +2031 -0
  22. pygeodesy/cartesianBase.py +1062 -0
  23. pygeodesy/clipy.py +704 -0
  24. pygeodesy/constants.py +516 -0
  25. pygeodesy/css.py +660 -0
  26. pygeodesy/datums.py +752 -0
  27. pygeodesy/deprecated/__init__.py +61 -0
  28. pygeodesy/deprecated/bases.py +40 -0
  29. pygeodesy/deprecated/classes.py +262 -0
  30. pygeodesy/deprecated/consterns.py +54 -0
  31. pygeodesy/deprecated/datum.py +40 -0
  32. pygeodesy/deprecated/functions.py +375 -0
  33. pygeodesy/deprecated/nvector.py +48 -0
  34. pygeodesy/deprecated/rhumbBase.py +32 -0
  35. pygeodesy/deprecated/rhumbaux.py +33 -0
  36. pygeodesy/deprecated/rhumbsolve.py +33 -0
  37. pygeodesy/deprecated/rhumbx.py +33 -0
  38. pygeodesy/dms.py +986 -0
  39. pygeodesy/ecef.py +1348 -0
  40. pygeodesy/elevations.py +279 -0
  41. pygeodesy/ellipsoidalBase.py +1224 -0
  42. pygeodesy/ellipsoidalBaseDI.py +913 -0
  43. pygeodesy/ellipsoidalExact.py +343 -0
  44. pygeodesy/ellipsoidalGeodSolve.py +343 -0
  45. pygeodesy/ellipsoidalKarney.py +403 -0
  46. pygeodesy/ellipsoidalNvector.py +685 -0
  47. pygeodesy/ellipsoidalVincenty.py +590 -0
  48. pygeodesy/ellipsoids.py +2476 -0
  49. pygeodesy/elliptic.py +1198 -0
  50. pygeodesy/epsg.py +243 -0
  51. pygeodesy/errors.py +804 -0
  52. pygeodesy/etm.py +1190 -0
  53. pygeodesy/fmath.py +1013 -0
  54. pygeodesy/formy.py +1818 -0
  55. pygeodesy/frechet.py +865 -0
  56. pygeodesy/fstats.py +760 -0
  57. pygeodesy/fsums.py +1898 -0
  58. pygeodesy/gars.py +358 -0
  59. pygeodesy/geodesicw.py +581 -0
  60. pygeodesy/geodesicx/_C4_24.py +1699 -0
  61. pygeodesy/geodesicx/_C4_27.py +2395 -0
  62. pygeodesy/geodesicx/_C4_30.py +3301 -0
  63. pygeodesy/geodesicx/__init__.py +48 -0
  64. pygeodesy/geodesicx/__main__.py +91 -0
  65. pygeodesy/geodesicx/gx.py +1382 -0
  66. pygeodesy/geodesicx/gxarea.py +535 -0
  67. pygeodesy/geodesicx/gxbases.py +154 -0
  68. pygeodesy/geodesicx/gxline.py +669 -0
  69. pygeodesy/geodsolve.py +426 -0
  70. pygeodesy/geohash.py +914 -0
  71. pygeodesy/geoids.py +1884 -0
  72. pygeodesy/hausdorff.py +892 -0
  73. pygeodesy/heights.py +1155 -0
  74. pygeodesy/interns.py +687 -0
  75. pygeodesy/iters.py +545 -0
  76. pygeodesy/karney.py +919 -0
  77. pygeodesy/ktm.py +633 -0
  78. pygeodesy/latlonBase.py +1766 -0
  79. pygeodesy/lazily.py +960 -0
  80. pygeodesy/lcc.py +684 -0
  81. pygeodesy/ltp.py +1107 -0
  82. pygeodesy/ltpTuples.py +1563 -0
  83. pygeodesy/mgrs.py +721 -0
  84. pygeodesy/named.py +1324 -0
  85. pygeodesy/namedTuples.py +683 -0
  86. pygeodesy/nvectorBase.py +695 -0
  87. pygeodesy/osgr.py +781 -0
  88. pygeodesy/points.py +1686 -0
  89. pygeodesy/props.py +628 -0
  90. pygeodesy/resections.py +1048 -0
  91. pygeodesy/rhumb/__init__.py +46 -0
  92. pygeodesy/rhumb/aux_.py +397 -0
  93. pygeodesy/rhumb/bases.py +1148 -0
  94. pygeodesy/rhumb/ekx.py +563 -0
  95. pygeodesy/rhumb/solve.py +572 -0
  96. pygeodesy/simplify.py +647 -0
  97. pygeodesy/solveBase.py +472 -0
  98. pygeodesy/sphericalBase.py +724 -0
  99. pygeodesy/sphericalNvector.py +1264 -0
  100. pygeodesy/sphericalTrigonometry.py +1447 -0
  101. pygeodesy/streprs.py +627 -0
  102. pygeodesy/trf.py +2079 -0
  103. pygeodesy/triaxials.py +1484 -0
  104. pygeodesy/units.py +969 -0
  105. pygeodesy/unitsBase.py +349 -0
  106. pygeodesy/ups.py +538 -0
  107. pygeodesy/utily.py +1231 -0
  108. pygeodesy/utm.py +762 -0
  109. pygeodesy/utmups.py +318 -0
  110. pygeodesy/utmupsBase.py +517 -0
  111. pygeodesy/vector2d.py +785 -0
  112. pygeodesy/vector3d.py +968 -0
  113. pygeodesy/vector3dBase.py +1049 -0
  114. pygeodesy/webmercator.py +383 -0
  115. pygeodesy/wgrs.py +439 -0
pygeodesy/lazily.py ADDED
@@ -0,0 +1,960 @@
1
+
2
+ # -*- coding: utf-8 -*-
3
+
4
+ u'''Lazily import C{pygeodesy} modules and attributes, based on
5
+ U{lazy_import<https://modutil.ReadTheDocs.io/en/latest/#lazy_import>}
6
+ from I{Brett Cannon}'s U{modutil<https://PyPI.org/project/modutil>}.
7
+
8
+ C{Lazy import} is I{supported only for }U{Python 3.7+
9
+ <https://Snarky.Ca/lazy-importing-in-python-3-7>} and is I{enabled by
10
+ default} in U{PyGeodesy 18.11.10<https://PyPI.org/project/PyGeodesy>}
11
+ I{and newer}.
12
+
13
+ To I{enable} C{lazy import}, set C{env} variable C{PYGEODESY_LAZY_IMPORT}
14
+ to C{1}, C{2}, C{3} or higher prior to C{import pygeodesy}. To I{disable}
15
+ C{lazy import}, set C{env} variable C{PYGEODESY_LAZY_IMPORT} to C{0} or
16
+ an empty string. Use C{2} or higher to print a message for each lazily
17
+ imported module and attribute, similar to C{env} variable C{PYTHONVERBOSE}
18
+ showing imports. Using C{3} or higher also shows the importing file name
19
+ and line number.
20
+
21
+ @note: C{Lazy import} applies only to top-level modules of C{pygeodesy}.
22
+ The C{lazy import} of a top-level module invariably loads all
23
+ sub-modules imported by that top-level module.
24
+
25
+ @note: C{Lazy import} raises a L{LazyAttributeError} or L{LazyImportError}
26
+ depending on the cause of the error and such errors can occur late,
27
+ after all initial imports.
28
+ '''
29
+
30
+ # from pygeodesy.errors import _xError2 # _ALL_MODS
31
+ from pygeodesy.interns import MISSING, NN, __all__ as _interns__all__, _areaOf_, \
32
+ _attribute_, _by_, _COLONSPACE_, _COMMASPACE_, \
33
+ _doesn_t_exist_, _DOT_, _enabled_, _EQUALSPACED_, \
34
+ _from_, _HASH_, _immutable_, _isclockwise_, _ispolar_, \
35
+ _NL_, _no_, _NorthPole_, _not_, _or_, _pygeodesy_, \
36
+ _line_, _module_, _pygeodesy_abspath_, _Python_, _QUOTE1_, \
37
+ _QUOTE2_, _SouthPole_, _SPACE_, _sub_packages, _UNDER_, \
38
+ _version_, _dunder_nameof, _headof, _tailof # _DEPRECATED_
39
+ from pygeodesy.interns import _intern # PYCHOK used!
40
+ # from pygeodesy.streprs import Fmt, pairs, unstr # _ALL_MODS
41
+ from pygeodesy import _isfrozen # handle as w/o lazy import
42
+
43
+ from os import getenv as _getenv # in .errors, .geodsolve, .props, .units
44
+ from os.path import basename as _basename
45
+ import sys as _sys # in .basics._sizeof
46
+ try:
47
+ from importlib import import_module
48
+ except ImportError: # Python 2.6-
49
+ def import_module(name, *package):
50
+ t = _ALL_MODS.streprs.unstr(import_module, name, *package)
51
+ raise LazyImportError(t, txt=_doesn_t_exist_)
52
+
53
+ _a_l_l_ = '__all__' # .__main__
54
+ __as__ = ' as '
55
+ _FOR_DOCS = _getenv('PYGEODESY_FOR_DOCS', NN) # for epydoc ...
56
+ _from_DOT__ = _SPACE_(NN, _from_, _DOT_)
57
+ _i0 = () # PYCHOK empty tuple
58
+ _init__all__ = _FOR_DOCS or _getenv('PYGEODESY_INIT__ALL__', _a_l_l_) == _a_l_l_ # PYCHOK expoted
59
+ _lazily_ = 'lazily'
60
+ _lazily_imported__ = _SPACE_(_HASH_, _lazily_, 'imported', NN)
61
+ _p_a_c_k_a_g_e_ = '__package__'
62
+ _PYGEODESY_GEOCONVERT_ = 'PYGEODESY_GEOCONVERT' # PYCHOK .mgrs, test.bases
63
+ _PYGEODESY_GEODSOLVE_ = 'PYGEODESY_GEODSOLVE' # PYCHOK .geodsolve, test.bases
64
+ _PYGEODESY_LAZY_IMPORT_ = 'PYGEODESY_LAZY_IMPORT'
65
+ _PYGEODESY_RHUMBSOLVE_ = 'PYGEODESY_RHUMBSOLVE' # PYCHOK .rhumb.solve, test.bases
66
+ _PYTHON_X_DEV = getattr(_sys, '_xoptions', {}).get('dev', # Python 3.2+
67
+ _getenv('PYTHONDEVMODE', NN)) # PYCHOK exported
68
+ _sys_version_info2 = _sys.version_info[:2] # in .basics, .fmath, ...
69
+ _unlazy = _unLazy0 = _isfrozen or _sys_version_info2 < (3, 7) # PYCHOK mod.__getattr__ 3.7+
70
+ _WARNINGS_X_DEV = _getenv('PYGEODESY_WARNINGS', NN) and (
71
+ _PYTHON_X_DEV or bool(_sys.warnoptions)) # PYCHOK .props
72
+ # @module_property[_RO?] <https://GitHub.com/jtushman/proxy_tools/>
73
+ isLazy = None # see @var isLazy in .__init__
74
+
75
+
76
+ class LazyAttributeError(AttributeError):
77
+ '''Raised if a C{lazily imported} attribute is missing or invalid.
78
+ '''
79
+ def __init__(self, *name_value, **txt):
80
+ _ALL_MODS.errors._error_init(AttributeError, self, name_value, **txt)
81
+
82
+
83
+ class LazyImportError(ImportError):
84
+ '''Raised if C{lazy import} is not supported, disabled or failed some other way.
85
+ '''
86
+ def __init__(self, *name_value, **txt):
87
+ _ALL_MODS.errors._error_init(ImportError, self, name_value, **txt)
88
+
89
+
90
+ class _Dict(dict):
91
+ '''(INTERNAL) Imports C{dict}.
92
+ '''
93
+ _name = NN
94
+
95
+ def __getattr__(self, attr):
96
+ try:
97
+ return self[attr]
98
+ except KeyError:
99
+ return dict.__getattr__(self, attr)
100
+
101
+ # def __setattr__(self, attr, value):
102
+ # if attr in self:
103
+ # self[attr] = value
104
+ # else:
105
+ # dict.__setattr__(self, attr, value)
106
+
107
+ def add(self, name, mod_, *subs):
108
+ '''Add a C{[name] = mod_} item.
109
+
110
+ @raise AssertionError: The B{C{name}} already exists
111
+ with a different B{C{mod_}}.
112
+ '''
113
+ if name in self:
114
+ sub = self[name] # duplicate OK
115
+ if sub != mod_ and sub not in subs: # PYCHOK no cover
116
+ t = _DOT_(self._name, name)
117
+ t = _COLONSPACE_(t, repr(sub))
118
+ t = _COMMASPACE_(t, _not_(repr(mod_)))
119
+ raise AssertionError(t)
120
+ else:
121
+ self[name] = mod_
122
+
123
+ def _NAME(self, which):
124
+ self._name = _intern(which.__name__.upper())
125
+
126
+
127
+ class _NamedEnum_RO(dict):
128
+ '''(INTERNAL) C{Read_Only} enum-like C{dict} sub-class.
129
+ '''
130
+ # _name = NN # also first kwd, __init__(_name=...)
131
+
132
+ def _DOT_(self, attr): # PYCHOK no cover
133
+ return _DOT_(self._name, attr) # PYCHOK _name
134
+
135
+ def __getattr__(self, attr):
136
+ try:
137
+ return self[attr]
138
+ except KeyError:
139
+ t = self._DOT_(attr)
140
+ raise LazyAttributeError(t, txt=_doesn_t_exist_)
141
+
142
+ def __setattr__(self, attr, value): # PYCHOK no cover
143
+ t = _EQUALSPACED_(self._DOT_(attr), value)
144
+ raise LazyAttributeError(t, txt=_immutable_)
145
+
146
+ def enums(self):
147
+ # Yield all C{(mod_, tuple)} pairs
148
+ for m, t in dict.items(self):
149
+ n = m.replace(_UNDER_, _DOT_)
150
+ if n != m:
151
+ if m.startswith(_UNDER_):
152
+ t = None # skip _name= ...
153
+ else:
154
+ u = m.rstrip(_UNDER_)
155
+ if u != m:
156
+ u = len(u)
157
+ n = n[:u] + m[u:]
158
+ if isinstance(t, tuple):
159
+ yield n, t
160
+
161
+ def fill_D(self, _D, which):
162
+ # Fill C{_Dict _D}.
163
+ _D._NAME(which)
164
+ _a = _D.add
165
+ for m, t in self.enums():
166
+ _a(m, _DOT_(m, NN, NN)) # import module
167
+ for a in t:
168
+ a, _, as_ = a.partition(__as__)
169
+ if as_: # import attr as attr_
170
+ _a(as_, _DOT_(m, a, NN), *_sub_packages)
171
+ else:
172
+ _a(a, m)
173
+ return _D
174
+
175
+
176
+ def _i(*names):
177
+ '''(INTERNAL) Intern all C{names}.
178
+ '''
179
+ return tuple(map(_intern, names)) if names else _i0
180
+
181
+
182
+ def _ALL_ATTRS(*attrs):
183
+ '''(INTERNAL) Unravel all exported module attributes.
184
+ '''
185
+ t = ()
186
+ for attr in attrs:
187
+ t += tuple(map(_attrof, attr))
188
+ return t
189
+
190
+
191
+ _ALL_INIT = _i(_pygeodesy_abspath_, _version_)
192
+
193
+ # __all__ value for most modules, accessible as _ALL_LAZY.<module>
194
+ _ALL_LAZY = _NamedEnum_RO(_name='_ALL_LAZY',
195
+ albers=_i('AlbersEqualArea', 'AlbersEqualArea2', 'AlbersEqualArea4',
196
+ 'AlbersEqualAreaCylindrical', 'AlbersEqualAreaNorth', 'AlbersEqualAreaSouth',
197
+ 'AlbersError', 'Albers7Tuple'),
198
+ auxilats=_i(), # module only
199
+ azimuthal=_i('AzimuthalError', 'Azimuthal7Tuple',
200
+ 'Equidistant', 'EquidistantExact', 'EquidistantGeodSolve', 'EquidistantKarney',
201
+ 'Gnomonic', 'GnomonicExact', 'GnomonicGeodSolve', 'GnomonicKarney',
202
+ 'LambertEqualArea', 'Orthographic', 'Stereographic',
203
+ 'equidistant', 'gnomonic'),
204
+ basics=_i('clips', 'copysign0', 'copytype', 'halfs2',
205
+ 'int1s', 'isbool', 'isCartesian', 'isclass', 'iscomplex', 'isDEPRECATED', 'isfloat',
206
+ 'isidentifier', 'isinstanceof', 'isint', 'iskeyword', 'isLatLon', 'islistuple',
207
+ 'isNvector', 'isodd', 'isscalar', 'issequence', 'isstr', 'issubclassof', 'itemsorted',
208
+ 'len2', 'map1', 'map2', 'neg', 'neg_',
209
+ 'signBit', 'signOf', 'splice', 'str2ub', 'ub2str', 'unsigned0'),
210
+ booleans=_i('BooleanFHP', 'BooleanGH', 'LatLonFHP', 'LatLonGH',
211
+ 'isBoolean'),
212
+ cartesianBase=_i('RadiusThetaPhi3Tuple', 'rtp2xyz', 'rtp2xyz_', 'xyz2rtp', 'xyz2rtp_'),
213
+ clipy=_i('ClipCS4Tuple', 'ClipFHP4Tuple', 'ClipGH4Tuple', 'ClipLB6Tuple', 'ClipSH3Tuple',
214
+ 'clipCS4', 'clipFHP4', 'clipGH4', 'clipLB6', 'clipSH', 'clipSH3'),
215
+ css=_i('CassiniSoldner', 'Css', 'CSSError', 'toCss',
216
+ 'EasNorAziRk4Tuple', 'EasNorAziRkEqu6Tuple', 'LatLonAziRk4Tuple'),
217
+ constants=_i('DIG', 'EPS', 'EPS0', 'EPS02', 'EPS1', 'EPS2', 'EPS4', 'EPS_2',
218
+ 'INF', 'INT0', 'MANT_DIG', 'MAX', 'MAX_EXP', 'MIN', 'MIN_EXP', 'NAN', 'NEG0', 'NINF',
219
+ 'PI', 'PI2', 'PI_2', 'PI3', 'PI_3', 'PI3_2', 'PI4', 'PI_4',
220
+ 'R_FM', 'R_GM', 'R_KM', 'R_M', 'R_MA', 'R_MB', 'R_NM', 'R_QM', 'R_SM', 'R_VM',
221
+ 'float_', 'float0_', 'isclose', 'isfinite', 'isinf', 'isint0',
222
+ 'isnan', 'isnear0', 'isnear1', 'isnear90', 'isneg0', 'isninf', 'isnon0',
223
+ 'remainder'),
224
+ datums=_i('Datum', 'Datums', 'Transform', 'Transforms'),
225
+ # deprecated=_i(), # module only
226
+ dms=_i('F_D', 'F_DM', 'F_DMS', 'F_DEG', 'F_MIN', 'F_SEC', 'F_D60', 'F__E', 'F__F', 'F__G', 'F_RAD',
227
+ 'F_D_', 'F_DM_', 'F_DMS_', 'F_DEG_', 'F_MIN_', 'F_SEC_', 'F_D60_', 'F__E_', 'F__F_', 'F__G_', 'F_RAD_',
228
+ 'F_D__', 'F_DM__', 'F_DMS__', 'F_DEG__', 'F_MIN__', 'F_SEC__', 'F_D60__', 'F__E__', 'F__F__', 'F__G__', 'F_RAD__',
229
+ 'S_DEG', 'S_MIN', 'S_SEC', 'S_DMS', 'S_RAD', 'S_SEP',
230
+ 'bearingDMS', 'clipDegrees', 'clipRadians', 'compassDMS', 'compassPoint',
231
+ 'degDMS', 'latDMS', 'latlonDMS', 'latlonDMS_', 'lonDMS', 'normDMS',
232
+ 'parseDDDMMSS', 'parseDMS', 'parseDMS2', 'parse3llh', 'parseRad', 'precision', 'toDMS'),
233
+ ecef=_i('EcefError', 'EcefFarrell21', 'EcefFarrell22', 'EcefKarney', 'EcefMatrix',
234
+ 'EcefSudano', 'Ecef9Tuple', 'EcefVeness', 'EcefYou'),
235
+ elevations=_i('Elevation2Tuple', 'GeoidHeight2Tuple',
236
+ 'elevation2', 'geoidHeight2'),
237
+ ellipsoidalBase=_i(), # module only
238
+ ellipsoidalBaseDI=_i(), # module only
239
+ ellipsoidalExact=_i(), # module only
240
+ ellipsoidalGeodSolve=_i(), # module only
241
+ ellipsoidalKarney=_i(), # module only
242
+ ellipsoidalNvector=_i(), # module only
243
+ ellipsoidalVincenty=_i('VincentyError',), # nothing else
244
+ ellipsoids=_i('a_f2Tuple', 'Circle4Tuple', 'Curvature2Tuple',
245
+ 'Ellipsoid', 'Ellipsoid2', 'Ellipsoids',
246
+ 'a_b2e', 'a_b2e2', 'a_b2e22', 'a_b2e32', 'a_b2f', 'a_b2f_', 'a_b2f2', 'a_b2n',
247
+ 'a_f2b', 'a_f_2b', 'b_f2a', 'b_f_2a',
248
+ 'e2f', 'e22f',
249
+ 'f2e2', 'f2e22', 'f2e32', 'f_2f', 'f2f_', 'f2f2', 'f2n', 'n2e2', 'n2f', 'n2f_'),
250
+ elliptic=_i('Elliptic', 'EllipticError', 'Elliptic3Tuple'),
251
+ epsg=_i('Epsg', 'EPSGError'),
252
+ errors=_i('AuxError', 'ClipError', 'CrossError', 'GeodesicError', 'IntersectionError',
253
+ 'NumPyError', 'LenError', 'LimitError', 'MGRSError',
254
+ 'ParseError', 'PointsError', 'RangeError', 'RhumbError',
255
+ 'SciPyError', 'SciPyWarning', 'TRFError', 'TriangleError', 'UnitError', 'VectorError',
256
+ 'crosserrors', 'exception_chaining', 'isError', 'limiterrors', 'rangerrors'),
257
+ etm=_i('Etm', 'ETMError', 'ExactTransverseMercator',
258
+ 'parseETM5', 'toEtm8'),
259
+ fmath=_i('Fdot', 'Fhorner', 'Fhypot', 'Fpolynomial', 'Fpowers', 'Fn_rt', 'Fcbrt', 'Fsqrt',
260
+ 'bqrt', 'cbrt', 'cbrt2', 'euclid', 'euclid_',
261
+ 'facos1', 'fasin1', 'fatan', 'fatan1', 'fatan2', 'favg',
262
+ 'fdot', 'fdot3', 'fmean', 'fmean_', 'fhorner', 'fidw', 'fpolynomial',
263
+ 'fpowers', 'fprod', 'frange', 'freduce', 'fremainder',
264
+ 'hypot', 'hypot_', 'hypot1', 'hypot2', 'hypot2_',
265
+ 'norm2', 'norm_', 'sqrt0', 'sqrt3', 'sqrt_a', 'zcrt', 'zqrt'),
266
+ formy=_i('Radical2Tuple',
267
+ 'antipode', 'antipode_', 'bearing', 'bearing_',
268
+ 'compassAngle', 'cosineForsytheAndoyerLambert', 'cosineForsytheAndoyerLambert_',
269
+ 'cosineAndoyerLambert', 'cosineAndoyerLambert_', 'cosineLaw', 'cosineLaw_',
270
+ 'equirectangular', 'equirectangular_', 'euclidean', 'euclidean_',
271
+ 'excessAbc_', 'excessCagnoli_', 'excessGirard_', 'excessLHuilier_',
272
+ 'excessKarney', 'excessKarney_', 'excessQuad', 'excessQuad_',
273
+ 'flatLocal', 'flatLocal_', 'flatPolar', 'flatPolar_',
274
+ 'hartzell', 'haversine', 'haversine_', 'heightOf', 'heightOrthometric', 'horizon', 'hubeny', 'hubeny_',
275
+ 'intersection2', 'intersections2', 'isantipode', 'isantipode_', 'isnormal', 'isnormal_',
276
+ 'latlon2n_xyz', 'normal', 'normal_', 'n_xyz2latlon', 'n_xyz2philam',
277
+ 'opposing', 'opposing_', 'philam2n_xyz', 'radical2',
278
+ 'thomas', 'thomas_', 'vincentys', 'vincentys_'),
279
+ frechet=_i('Frechet', 'FrechetDegrees', 'FrechetError', 'FrechetRadians',
280
+ 'FrechetCosineAndoyerLambert', 'FrechetCosineForsytheAndoyerLambert',
281
+ 'FrechetCosineLaw', 'FrechetDistanceTo', 'FrechetEquirectangular',
282
+ 'FrechetEuclidean', 'FrechetExact', 'FrechetFlatLocal', 'FrechetFlatPolar',
283
+ 'FrechetHaversine', 'FrechetHubeny', 'FrechetKarney', 'FrechetThomas',
284
+ 'FrechetVincentys', 'Frechet6Tuple',
285
+ 'frechet_'),
286
+ fstats=_i('Fcook', 'Flinear', 'Fwelford'),
287
+ fsums=_i('Fsum', 'Fsum2Tuple', 'ResidualError',
288
+ 'fsum', 'fsum_', 'fsumf_', 'fsum1', 'fsum1_', 'fsum1f_'),
289
+ gars=_i('Garef', 'GARSError'),
290
+ geodesicw=_i('Geodesic', 'GeodesicLine', 'Geodesic_WGS84'),
291
+ geodesicx=_i('gx', 'gxarea', 'gxbases', 'gxline', # modules, see _sub_packages
292
+ 'GeodesicAreaExact', 'GeodesicExact', 'GeodesicLineExact', 'PolygonArea'),
293
+ geodsolve=_i('GeodesicSolve', 'GeodesicLineSolve', 'GeodSolve12Tuple'),
294
+ geohash=_i('Geohash', 'GeohashError', 'Neighbors8Dict', 'Resolutions2Tuple'),
295
+ geoids=_i('GeoidError', 'GeoidG2012B', 'GeoidKarney', 'GeoidPGM', 'egmGeoidHeights',
296
+ 'PGMError', 'GeoidHeight5Tuple'),
297
+ hausdorff=_i('Hausdorff', 'HausdorffDegrees', 'HausdorffError', 'HausdorffRadians',
298
+ 'HausdorffCosineAndoyerLambert', 'HausdorffCosineForsytheAndoyerLambert',
299
+ 'HausdorffCosineLaw', 'HausdorffDistanceTo', 'HausdorffEquirectangular',
300
+ 'HausdorffEuclidean', 'HausdorffExact', 'HausdorffFlatLocal', 'HausdorffFlatPolar',
301
+ 'HausdorffHaversine', 'HausdorffHubeny', 'HausdorffKarney', 'HausdorffThomas',
302
+ 'HausdorffVincentys', 'Hausdorff6Tuple',
303
+ 'hausdorff_', 'randomrangenerator'),
304
+ heights=_i('HeightCubic', 'HeightError',
305
+ 'HeightIDWcosineAndoyerLambert', 'HeightIDWcosineForsytheAndoyerLambert',
306
+ 'HeightIDWcosineLaw', 'HeightIDWdistanceTo', 'HeightIDWequirectangular',
307
+ 'HeightIDWeuclidean', 'HeightIDWexact', 'HeightIDWflatLocal', 'HeightIDWflatPolar',
308
+ 'HeightIDWhaversine', 'HeightIDWhubeny', 'HeightIDWkarney', 'HeightIDWthomas',
309
+ 'HeightIDWvincentys', 'HeightLinear', 'HeightLSQBiSpline', 'HeightSmoothBiSpline'),
310
+ interns=_interns__all__,
311
+ iters=_i('LatLon2PsxyIter', 'PointsIter', 'points2',
312
+ 'isNumpy2', 'isPoints2', 'isTuple2', 'iterNumpy2', 'iterNumpy2over'),
313
+ karney=_i('Area3Tuple', 'Caps', 'Direct9Tuple', 'GDict', 'Inverse10Tuple', 'Rhumb8Tuple'),
314
+ ktm=_i('KTMError', 'KTransverseMercator'),
315
+ latlonBase=_i(), # module only
316
+ lazily=_i('LazyAttributeError', 'LazyImportError', 'isLazy', 'print_', 'printf'),
317
+ lcc=_i('Conic', 'Conics', 'Lcc', 'LCCError', 'toLcc'),
318
+ ltp=_i('Attitude', 'AttitudeError', 'ChLV', 'ChLVa', 'ChLVe', 'Frustum',
319
+ 'LocalCartesian', 'LocalError', 'Ltp', 'tyr3d'),
320
+ ltpTuples=_i('Aer', 'Aer4Tuple', 'Attitude4Tuple',
321
+ 'ChLVEN2Tuple', 'ChLV9Tuple', 'ChLVYX2Tuple', 'ChLVyx2Tuple',
322
+ 'Enu', 'Enu4Tuple', 'Footprint5Tuple', 'Local9Tuple', 'Los',
323
+ 'Ned', 'Ned4Tuple', 'Uvw', 'Uvw3Tuple', 'XyzLocal', 'Xyz4Tuple'),
324
+ mgrs=_i('Mgrs', 'parseMGRS', 'toMgrs', 'Mgrs4Tuple', 'Mgrs6Tuple'),
325
+ named=_i('ADict',
326
+ 'callername', 'classname', 'classnaming', 'modulename',
327
+ 'nameof', 'notImplemented', 'notOverloaded'),
328
+ namedTuples=_i('Bearing2Tuple', 'Bounds2Tuple', 'Bounds4Tuple',
329
+ 'Destination2Tuple', 'Destination3Tuple',
330
+ 'Distance2Tuple', 'Distance3Tuple', 'Distance4Tuple',
331
+ 'EasNor2Tuple', 'EasNor3Tuple', 'Forward4Tuple', 'Intersection3Tuple',
332
+ 'LatLon2Tuple', 'LatLon3Tuple', 'LatLon4Tuple',
333
+ 'LatLonDatum3Tuple', 'LatLonDatum5Tuple',
334
+ 'LatLonPrec3Tuple', 'LatLonPrec5Tuple',
335
+ 'NearestOn2Tuple', 'NearestOn3Tuple', 'NearestOn6Tuple', 'NearestOn8Tuple',
336
+ 'PhiLam2Tuple', 'PhiLam3Tuple', 'PhiLam4Tuple', 'Point3Tuple', 'Points2Tuple',
337
+ 'Reverse4Tuple', 'Triangle7Tuple', 'Triangle8Tuple', 'Trilaterate5Tuple',
338
+ 'UtmUps2Tuple', 'UtmUps5Tuple', 'UtmUps8Tuple', 'UtmUpsLatLon5Tuple',
339
+ 'Vector2Tuple', 'Vector3Tuple', 'Vector4Tuple'),
340
+ nvectorBase=_i(_NorthPole_, _SouthPole_),
341
+ osgr=_i('Osgr', 'OSGRError', 'parseOSGR', 'toOsgr'),
342
+ points=_i('LatLon_', 'LatLon2psxy', 'Numpy2LatLon', 'Shape2Tuple', 'Tuple2LatLon',
343
+ _areaOf_, 'boundsOf', 'centroidOf', 'fractional',
344
+ _isclockwise_, 'isconvex', 'isconvex_', 'isenclosedBy', _ispolar_,
345
+ 'luneOf', 'nearestOn5', 'perimeterOf', 'quadOf'),
346
+ props=_i('Property', 'Property_RO', 'property_RO', 'property_doc_',
347
+ 'deprecated_class', 'deprecated_function', 'deprecated_method',
348
+ 'deprecated_Property_RO', 'deprecated_property_RO', 'DeprecationWarnings'),
349
+ resections=_i('Collins5Tuple', 'ResectionError', 'Survey3Tuple', 'Tienstra7Tuple',
350
+ 'TriAngle5Tuple', 'TriSide2Tuple', 'TriSide4Tuple',
351
+ 'cassini', 'collins5', 'pierlot', 'pierlotx', 'tienstra7',
352
+ 'snellius3', 'wildberger3',
353
+ 'triAngle', 'triAngle5', 'triArea', 'triSide', 'triSide2', 'triSide4'),
354
+ rhumb=_i(), # module only
355
+ rhumb_aux_=_i('RhumbAux', 'RhumbLineAux'),
356
+ rhumb_ekx=_i('Rhumb', 'RhumbLine'),
357
+ rhumb_solve=_i('RhumbSolve', 'RhumbLineSolve', 'RhumbSolve7Tuple'),
358
+ sphericalBase=_i(), # module only
359
+ sphericalNvector=_i(), # module only
360
+ sphericalTrigonometry=_i(), # module only
361
+ simplify=_i('simplify1', 'simplifyRDP', 'simplifyRDPm', 'simplifyRW', 'simplifyVW', 'simplifyVWm'),
362
+ solveBase=_i(), # module only
363
+ streprs=_i('anstr', 'attrs', 'enstr2', 'fstr', 'fstrzs', 'hstr', 'instr',
364
+ 'lrstrip', 'pairs', 'reprs', 'strs', 'unstr'),
365
+ trf=_i('RefFrame', 'RefFrames', 'TransformXform', 'TRFXform', 'TRFXform7Tuple',
366
+ 'date2epoch', 'epoch2date', 'trfTransform0', 'trfTransforms', 'trfXform'),
367
+ triaxials=_i('BetaOmega2Tuple', 'BetaOmega3Tuple', 'Jacobi2Tuple',
368
+ 'JacobiConformal', 'JacobiConformalSpherical',
369
+ 'Triaxial', 'Triaxial_', 'TriaxialError', 'Triaxials', 'hartzell4'),
370
+ units=_i('Band', 'Bearing', 'Bearing_', 'Bool',
371
+ 'Degrees', 'Degrees_', 'Degrees2', 'Distance', 'Distance_', 'Easting', 'Epoch',
372
+ 'Feet', 'FIx', 'Float_', 'Height', 'Height_', 'HeightX', 'Int_',
373
+ 'Lam', 'Lam_', 'Lat', 'Lat_', 'Lon', 'Lon_',
374
+ 'Meter', 'Meter_', 'Meter2', 'Meter3', 'Northing', 'Number_',
375
+ 'Phi', 'Phi_', 'Precision_', 'Radians', 'Radians_', 'Radians2',
376
+ 'Radius_', 'Scalar', 'Scalar_', 'Zone'),
377
+ unitsBase=_i('Float', 'Int', 'Radius', 'Str'),
378
+ ups=_i('Ups', 'UPSError', 'parseUPS5', 'toUps8', 'upsZoneBand5'),
379
+ utily=_i('acos1', 'acre2ha', 'acre2m2', 'asin1', 'atan1', 'atan1d', 'atan2b', 'atan2d',
380
+ 'chain2m', 'circle4', 'cot', 'cot_', 'cotd', 'cotd_',
381
+ 'degrees', 'degrees90', 'degrees180', 'degrees360', 'degrees2grades', 'degrees2m',
382
+ # 'degrees2grades as degrees2gons',
383
+ 'fathom2m', 'ft2m', 'furlong2m',
384
+ 'grades', 'grades400', 'grades2degrees', 'grades2radians',
385
+ # 'grades as gons', 'grades400 as gons400', 'grades2degrees as gons2degrees', 'grades2radians as gons2radians',
386
+ 'km2m', 'm2chain', 'm2degrees', 'm2fathom', 'm2ft', 'm2furlong',
387
+ 'm2km', 'm2NM', 'm2radians', 'm2SM', 'm2toise', 'm2yard', 'NM2m',
388
+ 'radians', 'radiansPI', 'radiansPI2', 'radiansPI_2', 'radians2m',
389
+ 'sincos2', 'SinCos2', 'sincos2_', 'sincos2d', 'sincos2d_', 'sincostan3', 'SM2m',
390
+ 'tand', 'tand_', 'tan_2', 'tanPI_2_2', 'toise2m', 'truncate',
391
+ 'unroll180', 'unrollPI',
392
+ 'wrap90', 'wrap180', 'wrap360', 'wrapPI_2', 'wrapPI', 'wrapPI2', 'wrap_normal',
393
+ 'yard2m'),
394
+ utm=_i('Utm', 'UTMError', 'parseUTM5', 'toUtm8', 'utmZoneBand5'),
395
+ utmups=_i('UtmUps', 'UTMUPSError', 'parseUTMUPS5', 'toUtmUps8',
396
+ 'utmupsValidate', 'utmupsValidateOK', 'utmupsZoneBand5'),
397
+ utmupsBase=_i(), # module only
398
+ vector2d=_i('Circin6Tuple', 'Circum3Tuple', 'Circum4Tuple', 'Meeus2Tuple', 'Radii11Tuple', 'Soddy4Tuple',
399
+ 'circin6', 'circum3', 'circum4_', 'meeus2', 'radii11', 'soddy4'),
400
+ vector3d=_i('Vector3d', 'intersection3d3', 'iscolinearWith', 'nearestOn', 'nearestOn6', 'parse3d',
401
+ 'trilaterate2d2', 'trilaterate3d2'),
402
+ vector3dBase=_i(), # module only
403
+ webmercator=_i('Wm', 'WebMercatorError', 'parseWM', 'toWm', 'EasNorRadius3Tuple'),
404
+ wgrs=_i('Georef', 'WGRSError'),)
405
+
406
+ _ALL_DEPRECATED = _NamedEnum_RO(_name='_ALL_DEPRECATED',
407
+ deprecated=_i('bases', 'datum', 'nvector', # DEPRECATED modules and ...
408
+ 'rhumbaux', 'rhumbBase', 'rhumbsolve', 'rhumbx'), # ... names
409
+ deprecated_bases=_i('LatLonHeightBase', 'points2'),
410
+ deprecated_classes=_i('ClipCS3Tuple', 'EasNorExact4Tuple', 'EcefCartesian',
411
+ 'HeightIDW', 'HeightIDW2', 'HeightIDW3', 'Helmert7Tuple',
412
+ 'LatLonExact4Tuple', 'NearestOn4Tuple', 'Ned3Tuple',
413
+ 'RefFrameError', 'Rhumb7Tuple', 'RhumbOrder2Tuple',
414
+ 'Transform7Tuple', 'TriAngle4Tuple', 'UtmUps4Tuple'),
415
+ deprecated_consterns=_i('EPS1_2', 'MANTIS', 'OK'),
416
+ deprecated_datum=_i('Curvature2Tuple', 'Datum', 'Ellipsoid', 'Transform', # assert
417
+ 'Datums', 'Ellipsoids', 'Transforms',
418
+ 'R_M', 'R_MA', 'R_MB', 'R_KM', 'R_NM', 'R_SM', 'R_FM', 'R_VM'),
419
+ deprecated_functions=_i('anStr', 'areaof', 'atand', 'bounds', # most of the DEPRECATED functions, except ...
420
+ 'clipCS3', 'clipDMS', 'clipStr', 'collins', 'copysign', # ... ellipsoidal, spherical flavors
421
+ 'decodeEPSG2', 'encodeEPSG', 'enStr2', 'equirectangular3',
422
+ 'excessAbc', 'excessGirard', 'excessLHuilier',
423
+ 'false2f', 'falsed2f', 'float0', 'fStr', 'fStrzs', 'hypot3',
424
+ 'inStr', 'isenclosedby', 'istuplist',
425
+ 'joined', 'joined_', 'nearestOn3', 'nearestOn4',
426
+ 'parseUTM', 'perimeterof', 'polygon', 'scalar', 'simplify2',
427
+ 'tienstra', 'toUtm', 'triAngle4',
428
+ 'unsign0', 'unStr', 'utmZoneBand2'),
429
+ deprecated_nvector=_i('LatLonNvectorBase', 'Nvector', 'sumOf', 'NorthPole', 'SouthPole'),)
430
+
431
+
432
+ class _ALL_MODS(object):
433
+ '''(INTERNAL) Memoize import of any L{pygeodesy} module.
434
+ '''
435
+ def _DOT_(self, name): # PYCHOK no cover
436
+ return _DOT_(self.__class__.__name__, name)
437
+
438
+ def __getattr__(self, name):
439
+ '''Get a C{pygeodesy} module or attribute by B{C{name}}.
440
+
441
+ @arg name: Un/qualified module or qualified attribute name (C{str}).
442
+
443
+ @raise ImportError: Importing module B{C{name}} failed.
444
+
445
+ @raise AttributeError: No attribute named B{C{name}}.
446
+ '''
447
+ try: # most likely ... module is already imported
448
+ return _sys.modules[_DOT_(_pygeodesy_, name)]
449
+ except KeyError:
450
+ pass
451
+
452
+ m = self.getmodule(name)
453
+ return m if _tailof(m.__name__) == name else \
454
+ getattr(m, _tailof(name))
455
+
456
+ def __setattr__(self, attr, value): # PYCHOK no cover
457
+ t = _EQUALSPACED_(self._DOT_(attr), repr(value))
458
+ raise AttributeError(_COLONSPACE_(t, _immutable_))
459
+
460
+ def getattr(self, name, *attr_dflt): # , parent=_pygeodesy_
461
+ '''Get an attribute of/or a C{pygeodesy} module.
462
+
463
+ @arg name: Un/qualified module name (C{str}).
464
+ @arg attr_dflt: Optional attribute name (C{str}) and
465
+ optional default value (any C{type}).
466
+
467
+ @return: The C{pygeodesy} module's attribute value.
468
+
469
+ @raise ImportError: Importing module B{C{name}} failed.
470
+
471
+ @raise AttributeError: No attribute named B{C{attr}}.
472
+ '''
473
+ v = self.getmodule(name)
474
+ if attr_dflt:
475
+ v = getattr(v, *attr_dflt)
476
+ return v
477
+
478
+ def getmodule(self, name, parent=_pygeodesy_):
479
+ '''Get a C{pygeodesy} module.
480
+
481
+ @arg name: Qualified module name (C{str}).
482
+
483
+ @return: The C{pygeodesy} module.
484
+
485
+ @raise ImportError: Importing module B{C{name}} failed.
486
+ '''
487
+ if _headof(name) != parent:
488
+ name = _DOT_(parent, name)
489
+ try:
490
+ return _sys.modules[name]
491
+ except KeyError:
492
+ return import_module(name, parent)
493
+
494
+ def items(self): # no module named 'items'
495
+ '''Yield the modules imported so far.
496
+ '''
497
+ for n, m in _sys.modules.items():
498
+ yield n, m
499
+
500
+ @property # property_RO
501
+ def name(self):
502
+ return self.__class__.__name__
503
+
504
+ _ALL_MODS = _ALL_MODS() # PYCHOK singleton
505
+
506
+ __all__ = _ALL_LAZY.lazily
507
+ __version__ = '24.02.22'
508
+
509
+
510
+ def _ALL_OTHER(*objs):
511
+ '''(INTERNAL) Get class and function B{C{objs}} for __all__.
512
+ '''
513
+ _interns = _ALL_MODS.interns # from pygeodesy import interns
514
+
515
+ def _interned(o): # intern'd base name
516
+ n = _tailof(_dunder_nameof(o))
517
+ i = NN(_UNDER_, n, _UNDER_) # intern'd
518
+ return getattr(_interns, i, n)
519
+
520
+ return tuple(map(_interned, objs)) # map2
521
+
522
+
523
+ if _FOR_DOCS:
524
+ _ALL_DOCS = _ALL_OTHER
525
+ # (INTERNAL) Only export B{C{objs.__name__}} when making the
526
+ # docs to force C{epydoc} to include certain classes, methods,
527
+ # functions and other names in the documentation. Using the
528
+ # C{epydoc --private ...} command line option tends to include
529
+ # too much internal documentation.
530
+ else:
531
+ def _ALL_DOCS(*unused):
532
+ return ()
533
+
534
+
535
+ def _all_deprecates():
536
+ '''(INTERNAL) Build C{dict} of all deprecated imports.
537
+ '''
538
+ _D = _ALL_DEPRECATES
539
+ if not _D:
540
+ _ALL_DEPRECATED.fill_D(_D, _all_deprecates) # see _all_imports()
541
+ return _D
542
+
543
+ _ALL_DEPRECATES = _Dict() # PYCHOK _ALL_DEPRECATED.imports()
544
+
545
+
546
+ def _all_imports():
547
+ '''(INTERNAL) Build C{dict} of all lazy imports.
548
+ '''
549
+ # imports naming conventions stored below - [<key>] = <from>:
550
+ # import <module> - [<module>] = <module>
551
+ # from <module> import <attr> - [<attr>] = <module>
552
+ # from pygeodesy import <attr> - [<attr>] = <attr>
553
+ # from <module> import <attr> as <name> - [<name>] = <module>.<attr>.
554
+ _D = _ALL_IMPORTS
555
+ if not _D:
556
+ _ALL_LAZY.fill_D(_D, _all_imports) # see _all_deprecates()
557
+ return _D
558
+
559
+ _ALL_IMPORTS = _Dict() # PYCHOK _ALL_LAZY.imports()
560
+
561
+
562
+ def _all_missing2(_all_):
563
+ '''(INTERNAL) Get diffs between pygeodesy.__all__ and lazily._all_imports.
564
+ '''
565
+ def _diff(one, two):
566
+ return tuple(sorted(a for a in one if a not in two))
567
+
568
+ _alzy = _Dict((a, a) for a in _ALL_INIT)
569
+ _alzy.update(_all_imports()) # without _all_backups!
570
+ return ((_DOT_(_lazily_, _all_imports.__name__), _diff(_all_, _alzy)),
571
+ (_DOT_(_pygeodesy_, _a_l_l_), _diff(_alzy.keys(), _all_)))
572
+
573
+
574
+ def _attrof(attr_as): # .testDeprecated
575
+ a_, _, as_ = attr_as.partition(__as__)
576
+ return as_ or a_.rstrip(_DOT_)
577
+
578
+
579
+ def _caller3(up): # in .named
580
+ '''(INTERNAL) Get 3-tuple C{(caller name, file name, line number)}
581
+ for the caller B{C{up}} stack frames in the Python call stack.
582
+ '''
583
+ # sys._getframe(1) ... 'importlib._bootstrap' line 1032,
584
+ # may throw a ValueError('call stack not deep enough')
585
+ f = _sys._getframe(up + 1)
586
+ return (f.f_code.co_name, # caller name
587
+ _basename(f.f_code.co_filename), # file name
588
+ f.f_lineno) # line number
589
+
590
+
591
+ def _lazy_attr(unused): # PYCHOK overwritten in _lazy_import
592
+ pass
593
+
594
+
595
+ # def _lazy_attributes(_name_):
596
+ # '''(INTERNAL) Return a function to C{B{_name_}.__getattr__(attr)}
597
+ # on lazily imported modules and sub-modules.
598
+ # '''
599
+ # if _unlazy:
600
+ # raise AssertionError(_COMMASPACE_(_name_, _not_(_DEPRECATED_)))
601
+ #
602
+ # def _getattr(attr, *dflt):
603
+ # try: # a module name
604
+ # return _ALL_MODS.getmodule(attr)
605
+ # except (AttributeError, ImportError):
606
+ # return _ALL_MODS.getattr(_name_, attr, *dflt)
607
+ #
608
+ # return _getattr
609
+
610
+
611
+ def _lazy_import2(pack): # MCCABE 14
612
+ '''Check for and set up C{lazy import}.
613
+
614
+ @arg pack: The name of the package (C{str}) performing the imports,
615
+ to help resolving relative imports, usually C{__package__}.
616
+
617
+ @return: 2-Tuple C{(package, getattr)} of the importing package for
618
+ easy reference within itself and the callable to be set to
619
+ C{package.__getattr__}.
620
+
621
+ @raise LazyAttributeError: The package, module or attribute name is
622
+ invalid or does not exist.
623
+
624
+ @raise LazyImportError: Lazy import not supported or not enabled or
625
+ an import failed.
626
+
627
+ @note: This is I{Brett Cannon}'s function U{modutil.lazy_import
628
+ <https://GitHub.com/brettcannon/modutil/blob/master/modutil.py>}
629
+ modified to handle the C{__all__} and C{__dir__} attributes and
630
+ call C{importlib.import_module(<module>.<name>, ...)} without
631
+ causing a C{ModuleNotFoundError}.
632
+
633
+ @see: The original U{modutil<https://PyPI.org/project/modutil>},
634
+ U{PEP 562<https://www.Python.org/dev/peps/pep-0562>} and the
635
+ U{new way<https://Snarky.Ca/lazy-importing-in-python-3-7/>}.
636
+ '''
637
+ if pack != _pygeodesy_ or _unlazy: # new in 3.7
638
+ t = _no_(_DOT_(pack, _lazy_import2.__name__)) # PYCHOK no cover
639
+ raise LazyImportError(t, txt=_Python_(_sys.version))
640
+
641
+ package, parent = _lazy_init2(pack) # _pygeodesy_
642
+
643
+ subpacks = set((parent, '__main__', NN) + tuple(
644
+ _DOT_(parent, s) for s in _sub_packages))
645
+ imports = _all_imports()
646
+ deprecates = _all_deprecates()
647
+
648
+ def __getattr__(name): # __getattr__ only for Python 3.7+
649
+ # only called once for each undefined pygeodesy attribute
650
+ mod = imports.get(name, NN) or deprecates.get(name, NN)
651
+ if mod:
652
+ # importlib.import_module() implicitly sets sub-modules
653
+ # on this module as appropriate for direct imports (see
654
+ # note in the _lazy_import2.__doc__ above).
655
+ if mod.endswith(_DOT_): # import mod[.attr] as name
656
+ mod, _, attr = mod[:-1].rpartition(_DOT_)
657
+ else: # from mod import name
658
+ attr = name
659
+ try:
660
+ t = _DOT_(pack, mod)
661
+ imported = import_module(t, parent)
662
+ except ImportError:
663
+ # <https://GitHub.com/mrJean1/PyGeodesy/issues/76>
664
+ raise LazyImportError(_no_(_module_), txt=t)
665
+ t = getattr(imported, _p_a_c_k_a_g_e_, None)
666
+ if t not in subpacks: # invalid module package
667
+ raise LazyImportError(_DOT_(mod, _p_a_c_k_a_g_e_), t)
668
+ if attr: # get the attribute
669
+ imported = getattr(imported, attr, MISSING)
670
+ if imported is MISSING: # PYCHOK no cover
671
+ t = _DOT_(mod, attr)
672
+ # <https://GitHub.com/mrJean1/PyGeodesy/issues/76>
673
+ raise LazyAttributeError(_no_(_attribute_), txt=t)
674
+
675
+ elif name in (_a_l_l_,): # XXX '_d_i_r_', '_m_e_m_b_e_r_s_'?
676
+ imported = _ALL_INIT + tuple(imports.keys())
677
+ else: # PYCHOK no cover
678
+ t = _no_(_module_, _or_, _attribute_)
679
+ # <https://GitHub.com/mrJean1/PyGeodesy/issues/76>
680
+ raise LazyAttributeError(t, txt=_DOT_(parent, name))
681
+
682
+ setattr(package, name, imported)
683
+ if isLazy > 1:
684
+ t = NN(_lazily_imported__, _DOT_(parent, name))
685
+ if mod and _tailof(mod) != name:
686
+ t = NN(t, _from_DOT__, mod)
687
+ if isLazy > 2:
688
+ try: # see C{_caller3}
689
+ _, f, s = _caller3(2)
690
+ t = _SPACE_(t, _by_, f, _line_, s)
691
+ except ValueError:
692
+ pass
693
+ printf(t) # XXX print
694
+
695
+ return imported # __getattr__
696
+
697
+ global _lazy_attr
698
+ _lazy_attr = __getattr__
699
+
700
+ return package, __getattr__ # _lazy_import2
701
+
702
+
703
+ # def _lazy_import_all(_name_):
704
+ # '''(INTERNAL) Return a function mimicking C{from B{__name__} import *},
705
+ # of all items, see .deprecated.__init__
706
+ # '''
707
+ # if _unlazy:
708
+ # raise AssertionError(_COMMASPACE_(_name_, _not_(_DEPRECATED_)))
709
+ #
710
+ # _getattr = _lazy_attributes(_name_) # _name_.__getattr__
711
+ # _import_start = _lazy_import_star(_name_, ALL_=_ALL_IMPORTS)
712
+ #
713
+ # def _import_all(attr, *dflt):
714
+ # return _import_star(_name_) if attr == _a_l_l_ else \
715
+ # _getattr(attr, *dflt)
716
+ #
717
+ # return _import_all
718
+
719
+
720
+ def _lazy_import_as(_name_):
721
+ '''(INTERNAL) Return a function to C{import B{__name__}.mod as mod}
722
+ I{of modules only}, see .deprecated, .rhumb or get an attribute
723
+ lazily exported by C{__name__}.
724
+ '''
725
+ if _unlazy:
726
+ return None
727
+
728
+ def _import_as(mod):
729
+ try:
730
+ return _ALL_MODS.getmodule(_DOT_(_name_, mod))
731
+ except ImportError:
732
+ return _lazy_attr(mod)
733
+
734
+ return _import_as
735
+
736
+
737
+ # def _lazy_import_star(_name_, ALL_=_ALL_DEPRECATES):
738
+ # '''(INTERNAL) Return a function to mimick C{from B{__name__} import *},
739
+ # of all DEPRECATED items, see .deprecated, .testDeprecated
740
+ # '''
741
+ # if _unlazy:
742
+ # raise AssertionError(_COMMASPACE_(_name_, _not_(_DEPRECATED_)))
743
+ #
744
+ # def _import_star(_into_):
745
+ # '''Do C{from B{__name__} import *} inside module C{B{__into__}}.
746
+ # '''
747
+ # d = dict()
748
+ # nm = _tailof(_name_)
749
+ # _g = _ALL_MODS.getattr # pygeodesy.__getattr__
750
+ # _h = _headof
751
+ # for a, m in ALL_.items():
752
+ # if _h(m) == nm:
753
+ # try:
754
+ # d[a] = _g(m, a)
755
+ # except (AttributeError, ImportError):
756
+ # pass
757
+ # _sys.modules[_into_].__dict__.update(d)
758
+ # return d.keys() # imported names
759
+ #
760
+ # return _import_star
761
+
762
+
763
+ # def _lazy_subs(_name_, force=_FOR_DOCS, over=False):
764
+ # '''(INTERNAL) Return the names of a package's sub-packages and
765
+ # update the package's C{__dict__} accordingly.
766
+ # '''
767
+ # sm = dict()
768
+ # if force and _name_ != '__main__':
769
+ # nm = _tailof(_name_)
770
+ # _a = _ALL_MODS.getattr
771
+ # _m = _ALL_MODS.getmodule
772
+ # d = _a(_name_, '__dict__', {})
773
+ # for n in _a(_name_, _a_l_l_, ()):
774
+ # try: # n is a class name, get its mod name
775
+ # m = _a(_name_, n).__module__
776
+ # n, s = m.split(_DOT_)[-2:]
777
+ # if n == nm and s not in sm:
778
+ # # like import m as s
779
+ # m = _m(m)
780
+ # sm[s] = m if over else d.get(s, m)
781
+ # except (AttributeError, ImportError, ValueError) as x:
782
+ # pass
783
+ # d.update(sm)
784
+ #
785
+ # return _ALL_OTHER(*sm.values())
786
+
787
+
788
+ def _lazy_init2(pack):
789
+ '''(INTERNAL) Initialize lazy import and set globals C{isLazy} and C{_unLazy0}.
790
+
791
+ @arg pack: The name of the package (C{str}) performing the imports,
792
+ to help resolving relative imports, usually C{__package__}.
793
+
794
+ @return: 2-Tuple C{(package, parent)} with the importing C{package}
795
+ for easy reference within itself and its name aka the
796
+ C{parent}, same as B{C{pack}}.
797
+
798
+ @raise LazyImportError: Lazy import not supported or not enabled,
799
+ an import failed or the package name is
800
+ invalid or does not exist.
801
+
802
+ @note: Global C{isLazy} is set accordingly.
803
+ '''
804
+ global isLazy, _unLazy0
805
+
806
+ z = _getenv(_PYGEODESY_LAZY_IMPORT_, None)
807
+ if z is None: # _PYGEODESY_LAZY_IMPORT_ not set
808
+ isLazy = 1 # ... but only by default on 3.7
809
+ else:
810
+ z = z.strip() # like PYTHONVERBOSE et.al.
811
+ isLazy = int(z) if z.isdigit() else (1 if z else 0)
812
+
813
+ _unLazy0 = _unlazy or not isLazy # pre-3.7 or w/o lazy import
814
+
815
+ if isLazy < 1: # not enabled
816
+ raise LazyImportError(_PYGEODESY_LAZY_IMPORT_, repr(z), txt=_not_(_enabled_))
817
+ if _getenv('PYTHONVERBOSE', None): # PYCHOK no cover
818
+ isLazy += 1
819
+
820
+ try: # to initialize in Python 3+
821
+ package = import_module(pack)
822
+ parent = package.__spec__.parent # __spec__ only in Python 3.7+
823
+ if parent != pack: # assert
824
+ t = _COMMASPACE_(parent, _not_(pack)) # PYCHOK no cover
825
+ raise AttributeError(_EQUALSPACED_('parent', t))
826
+
827
+ except (AttributeError, ImportError) as x:
828
+ isLazy = False # failed
829
+ raise LazyImportError(_lazy_init2.__name__, pack, cause=x)
830
+
831
+ return package, parent
832
+
833
+
834
+ def _pairs(*args, **kwds): # in .ktm
835
+ # from pygeodesy.streprs import pairs
836
+ return _ALL_MODS.streprs.pairs(*args, **kwds)
837
+
838
+
839
+ def print_(*args, **nl_nt_prefix_end_file_flush_sep): # PYCHOK no cover
840
+ '''Python 3+ C{print}-like formatting and printing.
841
+
842
+ @arg args: Arguments to be converted to C{str} and joined by B{C{sep}}
843
+ (any C{type}, all positional).
844
+ @kwarg nl_nt_prefix_end_file_flush_sep: Keyword arguments C{B{nl}=0}
845
+ for the number of leading blank lines (C{int}), C{B{nt}=0}
846
+ the number of trailing blank lines (C{int}), C{B{prefix}=NN}
847
+ to be inserted before the formatted text (C{str}) and Python
848
+ 3+ C{print} keyword arguments C{B{end}}, C{B{sep}}, C{B{file}}
849
+ and C{B{flush}}.
850
+
851
+ @return: Number of bytes written.
852
+ '''
853
+ return printf(NN, *args, **nl_nt_prefix_end_file_flush_sep)
854
+
855
+
856
+ def printf(fmt, *args, **nl_nt_prefix_end_file_flush_sep_kwds):
857
+ '''C{Printf-style} and Python 3+ C{print}-like formatting and printing.
858
+
859
+ @arg fmt: U{Printf-style<https://Docs.Python.org/3/library/stdtypes.html#
860
+ printf-style-string-formatting>} format specification (C{str}).
861
+ @arg args: Arguments to be formatted (any C{type}, all positional).
862
+ @kwarg nl_nt_prefix_end_file_flush_sep_kwds: Keyword arguments C{B{nl}=0}
863
+ for the number of leading blank lines (C{int}), C{B{nt}=0} the
864
+ number of trailing blank lines (C{int}), C{B{prefix}=NN} to
865
+ be inserted before the formatted text (C{str}) and Python 3+
866
+ C{print} keyword arguments C{B{end}}, C{B{sep}}, C{B{file}} and
867
+ C{B{flush}}. Any remaining C{B{kwds}} are U{printf-style
868
+ <https://Docs.Python.org/3/library/stdtypes.html#printf-style-string-formatting>}
869
+ keyword arguments to be formatted, I{iff no B{C{args}} are present}.
870
+
871
+ @return: Number of bytes written.
872
+ '''
873
+ b, e, s, f, fl, p, kwds = _xprint7(**nl_nt_prefix_end_file_flush_sep_kwds)
874
+ try:
875
+ if args:
876
+ t = (fmt % args) if fmt else s.join(map(str, args))
877
+ elif kwds: # PYCHOK no cover
878
+ t = (fmt % kwds) if fmt else s.join(_pairs(kwds, prec=p))
879
+ else: # PYCHOK no cover
880
+ t = fmt
881
+ except Exception as x:
882
+ _E, s = _ALL_MODS.errors._xError2(x)
883
+ unstr = _ALL_MODS.streprs.unstr
884
+ t = unstr(printf, fmt, *args, **nl_nt_prefix_end_file_flush_sep_kwds)
885
+ raise _E(s, txt=t, cause=x)
886
+ try:
887
+ n = f.write(NN(b, t, e))
888
+ except UnicodeEncodeError: # XXX only Windows
889
+ t = t.replace('\u2032', _QUOTE1_).replace('\u2033', _QUOTE2_)
890
+ n = f.write(NN(b, t, e))
891
+ if fl: # PYCHOK no cover
892
+ f.flush()
893
+ return n
894
+
895
+
896
+ def _xprint7(nl=0, nt=0, prec=6, prefix=NN, sep=_SPACE_, file=_sys.stdout,
897
+ end=_NL_, flush=False, **kwds):
898
+ '''(INTERNAL) Unravel the C{printf} and remaining keyword arguments.
899
+ '''
900
+ if nl > 0:
901
+ prefix = NN(_NL_ * nl, prefix)
902
+ if nt > 0:
903
+ end = NN(end, _NL_ * nt)
904
+ return prefix, end, sep, file, flush, prec, kwds
905
+
906
+
907
+ # del _i, _i0, _intern
908
+
909
+ if __name__ == '__main__':
910
+
911
+ from timeit import timeit
912
+
913
+ def t1():
914
+ from pygeodesy.trf import RefFrame
915
+ return RefFrame
916
+
917
+ def t2():
918
+ return _ALL_MODS.trf.RefFrame
919
+
920
+ assert t1() is t2() # prime each
921
+
922
+ t1 = timeit(t1, number=1000000)
923
+ t2 = timeit(t2, number=1000000)
924
+ v = _Python_(_sys.version)
925
+ printf('%.8f import vs %.8f _ALL_MODS: %.3fX, %s', t1, t2, t2 / t1, v)
926
+ del t1, t2, v
927
+
928
+ # python3.12 -m pygeodesy.lazily
929
+ # 0.13352763 import vs 0.70804508 _ALL_MODS: 5.303X, Python 3.12.0
930
+
931
+ # % python3.11 -W ignore -m pygeodesy.lazily
932
+ # 0.37998008 import vs 0.79537812 _ALL_MODS: 2.093X, Python 3.11.5
933
+
934
+ # % python3.10 -W ignore -m pygeodesy.lazily
935
+ # 0.39046367 import vs 0.90492925 _ALL_MODS: 2.318X, Python 3.10.8
936
+
937
+ # % python2 -m pygeodesy.lazily
938
+ # 1.17563510 import vs 2.02626395 _ALL_MODS: 1.724X, Python 2.7.18
939
+
940
+ # **) MIT License
941
+ #
942
+ # Copyright (C) 2018-2024 -- mrJean1 at Gmail -- All Rights Reserved.
943
+ #
944
+ # Permission is hereby granted, free of charge, to any person obtaining a
945
+ # copy of this software and associated documentation files (the "Software"),
946
+ # to deal in the Software without restriction, including without limitation
947
+ # the rights to use, copy, modify, merge, publish, distribute, sublicense,
948
+ # and/or sell copies of the Software, and to permit persons to whom the
949
+ # Software is furnished to do so, subject to the following conditions:
950
+ #
951
+ # The above copyright notice and this permission notice shall be included
952
+ # in all copies or substantial portions of the Software.
953
+ #
954
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
955
+ # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
956
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
957
+ # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
958
+ # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
959
+ # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
960
+ # OTHER DEALINGS IN THE SOFTWARE.